JVM 心得分享(加载 链接 初始化)
Java虚拟机(JVM)是Java语言的核心且重要的组成部分,了解JVM的加载、链接、初始化过程,对于Java程序员来说也是至关重要的。本文将对JVM的加载、链接、初始化过程进行详细讲解,并提供两个示例说明。
加载
在JVM运行Java程序时,需要在内存中加载所需的Java类文件,也就是将代码装载到内存中执行。JVM的类加载器可以分为三类:
- 启动类加载器(Bootstrap Class Loader):该加载器使用C++编写,并不是Java类,其负责在JVM启动时加载核心类库和JVM初始化操作。
- 扩展类加载器(Extension Class Loader):该加载器负责加载扩展类路径(JAVA_HOME/lib/ext目录)下的类库。
- 应用程序类加载器(Application Class Loader):该加载器负责加载应用程序的类路径(CLASSPATH)下的类库。
类加载器按照委托机制进行加载,即父加载器代理子加载器进行加载,在子加载器找不到类的情况下才由父加载器进行加载。
链接
类在加载到内存中之后,还需要进行链接,其中包括三个步骤:
验证
在验证阶段,JVM会检查类文件的正确性和安全性,查看是否符合JVM规范,在验证成功之后才能被加载执行。
准备
在准备阶段,JVM会为类变量(static变量)分配内存并设置初始值(0或null)。在该阶段,还不会执行初始化器中的代码。
解析
在解析阶段,JVM会将类中的符号引用转化为直接引用,即将类中的常量池中的符号引用替换为直接指向内存地址的引用。
初始化
在类加载和链接完成后,就会进入初始化阶段,也是类的生命周期中的最后一个阶段,在该阶段会为类变量赋值并执行初始化器中的代码。类的初始化顺序遵循类的继承关系,先初始化父类,然后再初始化子类。
下面,我们通过两个示例来更好地理解JVM的加载、链接、初始化过程:
示例一
public class InitializationDemo1 {
static {
i = 2;
// System.out.println(i); // 非法的前向引用
}
static int i = 1;
public static void main(String[] args) {
System.out.println(InitializationDemo1.i);
}
}
该程序输出结果为1,原因是在静态初始化块中后定义的变量i,故i=1,而非静态初始化块中定义的i=2。若将注释取消,程序会编译失败,提示非法的前向引用,这是因为i定义在静态初始化块之后,尚未声明。
示例二
public class InitializationDemo2 {
public static void main(String[] args) {
System.out.println(Base.value);
}
}
class Base {
static {
System.out.println("Base 静态初始化块");
}
static int value = 123;
}
class Sub extends Base {
static {
System.out.println("Sub 静态初始化块");
}
}
该程序的输出结果为“Base 静态初始化块”和“123”(Sub类没有被加载初始化)。这是因为执行到主函数所在的类时,虚拟机会初始化类的静态属性,触发Base类的初始化。类的初始化是按需进行的,只有首次实例化或对类的静态成员变量进行访问时才会触发。
以上就是JVM加载、链接、初始化的完整攻略。了解JVM的类加载机制、堆、栈等知识,有利于我们编写高效并可靠的Java程序。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JVM 心得分享(加载 链接 初始化) - Python技术站