最近接触了Java类加载器,突然认识到,不完全明白有人调用时会发生什么
java -jar App.jar
好吧,我猜
- 创建了一个新的 JVM 实例
- 它使用 ClassLoader 加载主类和其他类
- 字节码从 main() 方法开始执行
但我仍然认为有很多事情我需要了解更多。
- 谁以及如何决定在启动时应该加载哪些类以及曾经需要哪些类?
我发现了两个相关的问题,但没有解释如何将其应用于 Java 现实。
最近接触了Java类加载器,突然认识到,不完全明白有人调用时会发生什么
java -jar App.jar
好吧,我猜
但我仍然认为有很多事情我需要了解更多。
我发现了两个相关的问题,但没有解释如何将其应用于 Java 现实。
• 谁以及如何决定在启动时应该加载哪些类以及曾经需要哪些类?
我们需要了解java类加载的基础知识。最初,引导类加载器(它作为 VM 本身的一部分本地实现)负责加载核心系统类。然后还有其他类加载器,如扩展、系统、用户定义(可选)类加载器,它们决定何时以及如何加载类。 类加载的基础知识
决定由类加载器做出。有不同的实现,其中一些预加载它们可以加载的所有类,而另一些则仅在需要时加载类。
一个类只有在第一次从程序代码中访问时才需要加载;这种访问可能是该类中对象的实例化或对其static
成员之一的访问。通常,默认类加载器会在需要时延迟加载类。
但是,在任何情况下都不能依赖某些类来预加载:在Class.forName(...)
实际执行此代码之前,可能无法确定通过何种方式访问的类。
在其他选项中,对于简单的实验,您可以使用静态初始化程序代码来查看实际加载类的实际时间和顺序;此代码将在第一次加载类时执行;例子:
class SomeClass {
static {
System.out.println("Class SomeClass was initialized.");
}
public SomeClass() {
...
}
...
}
您的示例显示了一个可执行的 jar,它只是一个普通的 java 存档(jar),其清单文件(位于 folder "META_INF"
)中有一个额外的键/值对。键是“ Main-Class
”,如果您像示例中一样“运行”jar,则该类的“main”方法将被执行的类的完全限定类名的值。
jar 是一个 zip 文件,您可以使用每个 zip 存档工具查看内部文件。
每当您编译 Java 程序时,都会执行以下步骤
这将是第一阶段。
稍后解释器检查运行时错误,如果一切正常且无异常,则解释器将字节码转换为可执行代码。
Java 的第一阶段由 JIT 编译器(Just In Time)完成。