是什么导致加载Java类?

时间:2016-05-26 19:11:14

标签: java classloader

我正在尝试打开Java类文件,检测字节码并在将类加载到JVM之前保存类文件。我的问题是一个类“太快”加载到JVM中。在将类加载到JVM之后,将对字节码进行检测。

加载每个类时会输出

-verbose:class,但它不会告诉我是什么触发了JVM加载类。如何获得一个显示正在加载的类的调用堆栈?

在以下代码中放置一个断点,在初始化并且未加载类时显示调用堆栈。

static
{
    System.out.println("Initialized!");
}

注意:我知道我可以使用Java代理来执行此操作并保证字节码已经过检测。但是,我出于各种原因选择了这条路线。

2 个答案:

答案 0 :(得分:1)

我打开java.lang.ClassLoader并在loadClass(String name, boolean resolve)中设置条件断点。条件为arg0.endsWith("MyClass"),其中arg0name参数。触发断点时,IDE将显示调用堆栈。调用堆栈中的几个帧向下显示了为什么要加载类。

注意:此条件适用于Eclipse IDE,可能需要在其他IDE中进行一些调整。

答案 1 :(得分:0)

在Hotspot JVM上,它与Oracle和OpenJDK java发行版一起使用,在首次引用时会加载类。以下是https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html

的相关摘要
  

Java虚拟机通过使用引导类加载器(第5.3.1节)创建一个初始类来启动,该类以依赖于实现的方式指定。然后,Java虚拟机链接初始类,初始化它,并调用公共类方法void main(String [])。调用此方法会驱动所有进一步的执行。构成主方法的Java虚拟机指令的执行可能导致附加类和接口的链接(并因此创建),以及调用其他方法。

     

创建由名称N表示的类或接口C由Java虚拟机(第2.5.4节)的方法区域中构造的C的特定于实现的内部表示构成。类或接口创建被触发通过另一个类或接口D,它通过其运行时常量池引用C.类或接口创建也可能由某些Java SE平台类库(第2.12节)中的D调用方法(如反射)触发。

如果您希望自己实际执行字节码操作,并且在运行时,则至少有两个模型可供您选择遵循

  1. 使用类似于AspectJ的加载时间编织的东西,包括使用单独的类加载器和代理来响应类加载
  2. JRebel如何通过监控已知的.class文件获取更新的时间戳http://zeroturnaround.com/software/jrebel/learn/faq/
  3. 除非您自己非常强烈地需要这样做,否则请考虑使用上述工具之一。更好的是,确定Java注释和反射是否可以解决您尝试做的事情。