2

在阅读这个问题的答案时,我想知道 Java7 引导程序如何知道public static void main(String[] args)方法的存在,而不运行静态初始化程序?我对这个话题有一些假设,但其中一些显然是错误的:

  • Java Bootstrap 运行在 JVM 中,所以它只能使用标准的 JVM 特性(没有原生特性)——例如,被调用的类必须在 CLASSPATH 上
  • 标准的 JVM 类加载是通过普通的类加载机制完成的(我知道它有几个步骤,我已经玩过几次类加载器了)
  • 类被解析(链接)后,立即运行类初始化(包括初始化静态属性和运行静态初始化程序)
  • 没有办法分开前两个步骤

我的问题是:

  • 谁调用类初始值设定项以及在哪个阶段?(之前发生了什么,之后发生了什么?)
  • 为什么引导程序的行为与“正常”类加载不同?在这方面还有更多不同吗?
  • 额外的问题:我的哪个假设是错误的?

总结提到的问题:如果您运行 Java 主类(从 Java7 命令行),它将检查main()方法的存在,而不运行静态初始化程序。在 Java6 中,它的行为有所不同。

4

1 回答 1

4

可以在不链接的情况下加载一个类:Java 8 中的启动器通过调用类加载器上的loadClass方法来加载主类,该类加载器不链接该类或运行其任何静态方法。

有关加载_ Java 8 中的主类。

Java 6 启动器使用 FindClass JNI 方法来加载主类:我猜这是造成行为差异的原因。见 jdk6/jdk6/jdk/file/814bf0775b52/src/share/bin/java.c#l1387

FindClass 确实初始化了类,至少在 Java 6 上:jdk6/jdk6/hotspot/file/91e5cc5d33b9/src/share/vm/prims/jni.cpp 中的实现

result = find_class_from_class_loader(env, sym, true, loader, protection_domain, true, thread);

在 jdk6/jdk6/hotspot/file/91e5cc5d33b9/src/share/vm/prims/jvm_misc.hpp 中调用,

jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS);

以 init 为真

于 2015-09-08T21:12:44.277 回答