在Java Instrumentation代理中使用Class.forName() [英] Using Class.forName() in Java Instrumentation Agent
问题描述
我的理解是,如果我使用:
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)
wherecurrentLoader
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屋!