关于“深入理解Java类加载全过程”,下面是一份完整攻略,由以下几个部分构成:
背景
Java是一门面向对象的语言,其执行方式和传统的编译型语言有所不同。Java的执行分为编译阶段和运行阶段,其中涉及到Java类的加载、验证、准备、解析、初始化等环节。
类加载全过程
Java类的加载过程分为以下几步:
1. 加载
类加载器首先从CLASSPATH中找到指定类文件,读取类文件中的二进制数据,并将其存储在方法区(JDK1.8之前的永久代,JDK1.8之后是元空间)中,以便在JVM后续的执行过程中调用。
2. 验证
虚拟机需要进行类文件的验证以确保其符合Java虚拟机规范要求,主要包括以下验证内容:
- 文件格式验证:验证字节流是否符合Class文件格式的规范。
- 元数据验证:对字节码描述的信息进行语义分析,以保证其符合Java语言规范。
- 字节码验证:通过数据流和控制流分析,确定程序语义是否合法、符合逻辑。
- 符号引用验证:确保应用程序中的符号引用能够正确解析为引用的目标类或成员。
3. 准备
准备阶段是为类的静态变量分配内存并设置默认初始值,非静态变量不包括在准备阶段中,因为非静态变量是在对象实例化时才会进行初始化。
4. 解析
解析阶段将符号引用替换为直接引用的过程,也就是得到加载类所需的信息,例如在常量池中查找类、方法的直接引用等。
5. 初始化
类初始化阶段即执行类的构造器
示例说明
下面以两个示例说明Java类加载的全过程。
示例1
代码:
public class TestClassLoad {
public static void main(String[] args) {
Son s = new Son();
System.out.println(s.age);
}
}
class Grandpa {
public Grandpa() {
System.out.println("Grandpa()");
}
}
class Father extends Grandpa {
public Father() {
System.out.println("Father()");
}
}
class Son extends Father {
public int age = 10;
public Son() {
System.out.println("Son()");
}
}
输出结果:
Grandpa()
Father()
Son()
10
分析:
在程序开始执行时,先有类加载器加载了TestClassLoad类,当前正是处于初始化过程中,因此先会执行Grandpa类中的构造方法,打印出"Grandpa()"。接下来,Father类继承了Grandpa类,并调用了Grandpa的构造方法,紧接着执行自己的构造方法,打印出"Father()"。Son类同样继承了Father类,并分别调用了Grandpa和Father的构造方法,然后执行自己的构造方法,打印出"Son()"。最后,打印出Son的年龄为10。
示例2
代码:
public class TestClassLoad2 {
public static void main(String[] args) {
ClassLoader classLoader = TestClassLoad2.class.getClassLoader();
System.out.println(classLoader);
ClassLoader parentClassLoader = classLoader.getParent();
System.out.println(parentClassLoader);
ClassLoader grandClassLoader = parentClassLoader.getParent();
System.out.println(grandClassLoader);
}
}
输出结果:
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@3572469c
null
分析:
在示例2中,我们通过TestClassLoad2.class.getClassLoader()获取该类的类加载器对象,然后通过调用getParent()方法获取其父类加载器对象,最后我们再次调用getParent()方法获取其祖父类加载器对象。运行结果中打印出了该类加载器对象、其父类加载器对象和其祖父类加载器对象,分别是AppClassLoader、ExtClassLoader和null。因为Java虚拟机中的类加载器分为三层:启动类加载器、扩展类加载器和应用程序类加载器,而应用程序类加载器又叫作系统类加载器。
结论
通过上述的例子,我们可以看出Java类的加载过程并不是一蹴而就的,而是包括了加载、验证、准备、解析、初始化等环节,在这个过程中,Java虚拟机必须完成从加载到初始化的整个过程,才能为后续的执行提供支持。因此,我们需要充分理解Java类的加载过程,并在实际开发中根据实际情况进行优化和调整,从而保证程序的正常运行。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:深入理解Java 类加载全过程 - Python技术站