在Java Instrumentation代理中使用Class.forName() [英] Using Class.forName() in Java Instrumentation Agent

查看:171
本文介绍了在Java Instrumentation代理中使用Class.forName()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的理解是,如果我使用:

What I understand is that if I use:

Instrumentation#getAllLoadedClasses()

我确实获得了目标JVM选择的所有已加载类。但是如果我这样做:

I do get a selection of all loaded classes by the target JVM. But If I do:

Class.forName( my.class.name)

该类与VM加载的类不同。是的,我可以在代理MANIFEST.MF Class-Path中将该特定类添加为jar-但这与 getAllLoadedClasses()看起来不一样。

This will not be the same class as the class loaded by VM. Yes, I can add this particular class as a jar in the agent MANIFEST.MF Class-Path - but that does not look the same to me as getAllLoadedClasses().

有人可以确认这是否正确,即我无法使用 Class.forName()何时安装?我的目标不是使用 getAllLoadedClasses()遍历所有已加载的类-但是,如果没有其他选择,我想现在还可以。

Could someone please confirm whether this is correct i.e. I would not be able to find a specific class using Class.forName() when instrumenting? My objective was not to iterate over all loaded classes using getAllLoadedClasses() - But if there is no alternative, I guess that's okay for now.

** 更新

我写的一个错误是 Boot-Class -路径,现在我已在清单中对其进行了更正。使用 -verbose:class 日志记录,我设法看到我的jar是以

What I made a mistake in writing is the Boot-Class-Path which I have now corrected in my manifest. Using -verbose:class logging I managed to see that my jars are being loaded as

[Opened C:\fullpath\someother.jar]
[Opened C:\fullpath\another.jar]
[Opened C:\fullpath\different.jar]

但是我没有看到任何相应的加载信息。我尝试添加 Class.forName( a.package.in.someother.jar.classname)并得到NoClassDefFoundError。一旦进入代理jar,就无法使用 Class.forName()检查类是否由目标VM加载。我收到了NoClassDefFoundError。

But I don't see any corresponding loading information. I tried adding a Class.forName("a.package.in.someother.jar.classname") and got NoClassDefFoundError. As soon as I jump into the agent jar, I cannot use Class.forName() to check if the class is loaded by the target VM. I am getting a NoClassDefFoundError.

进一步更新

好的,我已经查找清单以查找我的 WEB-INF / lib 和tomcat的 lib 目录中的所有类。我可以看到以下内容:

Okay I have "Fattened" the manifest to look up all classes in my WEB-INF/lib and tomcat's lib directory. What I can see is below:

1)首次加载我的自定义类 MyClass 时。 -verbose 显示:

1) When my custom class MyClass is loaded for the first time. -verbose shows:

[Loaded my.pkg.MyClass from file:/C:/base/webapps/ROOT/WEB-INF/lib/mypkg.jar]

2)如果我尝试再次加载该类,则它正确显示了上述顺序。

2) If I try to load the class again, it is correctly showing the above order.

3)我的代理jar随同tomcat <$ c的所有类一起出现$ c> lib 和我的 web-inf / lib 目录。而且我还可以确认装载程序正确地看到了罐子。

3) My agent jar is manifested with all classes for my tomcat lib and my web-inf/lib directory. And I can also confirm that the loader sees the jars correctly.

4)现在,我注入了代理,并调用 Class.forName( my .pkg.MyClass)。我得到以下结果。

4) Now I inject the agent, and call Class.forName("my.pkg.MyClass") from within the agent class. I get the below results.

[Loaded my.pkg.MyClass from file:/C:/base/webapps/ROOT/WEB-INF/lib/mypkg.jar]

我承认它是系统类加载器,位于我的内部@RafaelWinterhalter的代理代码在他的答案之一中指出。有什么方法可以强制执行委派,以便使其他类加载器加载代理类,从而正确地重新定义类。

I acknowledge that it's system class loader loding it inside my agent code as @RafaelWinterhalter pointed out in one of his answers. Is there any way I can force a "Delegation" so that the a different classloader loads the agent class and therefore, correctly redefines a class.

我们将提供任何帮助。 / p>

Any help is appreciated.

推荐答案

如Javadoc中所述:

As it is stated in the javadoc:


调用此方法等效于:
Class.forName(className,true,currentLoader)
其中 currentLoader 表示当前类
的定义类加载器。

Invoking this method is equivalent to: Class.forName(className, true, currentLoader) where currentLoader denotes the defining class loader of the current class.

将该方法标记为 @CallerSensitive 的源代码,这意味着您会基于调用该方法的类加载器获得不同的结果。

You can also see from the source code that the method is marked @CallerSensitive which means that you get a different result based on the class loader that invokes the method.

调用 Instrumentation :: getAllLoadedClasses 时,返回的数组包含任何类加载器的类,而不仅包含当前类加载器的类,当前类加载器是运行时的系统类加载器Java代理。因此:

When calling Instrumentation::getAllLoadedClasses, the returned array contains classes of any class loader and not only of the current class loader which is the system class loader when running a Java agent. Therefore:

for (Class<?> type : instrumentation.getAllLoadedClasses()) {
  assert type == Class.forName(type.getName());
}

通常不是真的。

这篇关于在Java Instrumentation代理中使用Class.forName()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆