java - 在 Java Instrumentation Agent 中使用 Class.forName()

标签 java classloader instrumentation

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

Instrumentation#getAllLoadedClasses()

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

Class.forName("my.class.name")

这与 VM 加载的类不是同一个类。是的,我可以将这个特定的类作为 jar 添加到代理 MANIFEST.MF 类路径中 - 但这对我来说与 getAllLoadedClasses() 不同。

有人可以确认这是否正确,即我在检测时无法使用 Class.forName() 找到特定的类吗?我的目标不是使用 getAllLoadedClasses() 迭代所有加载的类 - 但如果没有其他选择,我想现在就可以了。

** 更新

我在编写时犯的错误是 Boot-Class-Path,我现在已在 list 中更正了该错误。使用 -verbose:class 日志记录我设法看到我的 jar 正在加载为

[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。

进一步更新

好吧,我已经“加肥”了 list ,以查找我的 WEB-INF/lib 和 tomcat 的 lib 目录中的所有类。我可以看到如下:

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

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

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

3) 我的代理 jar 包含我的 tomcat libweb-inf/lib 目录的所有类。我还可以确认加载器正确地看到了 jar。

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

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

我承认它是系统类加载器将其加载到我的代理代码中,正如 @RafaelWinterhalter 在他的一个答案中指出的那样。有什么方法可以强制“委托(delegate)”,以便不同的类加载器加载代理类,从而正确地重新定义类。

感谢任何帮助。

最佳答案

正如 javadoc 中所述:

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

从源代码中还可以看到,该方法被标记为@CallerSensitive,这意味着根据调用该方法的类加载器,您会得到不同的结果。

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

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

通常情况下并不正确。

关于java - 在 Java Instrumentation Agent 中使用 Class.forName(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46523055/

相关文章:

c++ - 停止通过 STL 容器调用重载的 new 和 delete 运算符

java - 从插件项目中类转换解析 Java 源代码时出现问题

jvm - Java类加载可视化/分析工具

java - 为什么我的程序的行为仅仅基于 Maven 依赖而改变?

java - Java 的持久性检测

java - Android JUnit 测试应用类

java - 关于tomcat-jdbc与Java版本的兼容性

java - 如何在 try catch block 中使用 for 循环

java - Eclipse、Orion、OSGi 开发环境设置 (Maqetta)

java - 日期差异(以天为单位)向不同日期返回相同的值