如何理解Java类装载机制?
Java虚拟机将类装载过程分为三个步骤:加载、链接、初始化。在程序运行过程中,类装载可以分为显式装载和隐式装载,其中显式装载是使用ClassLoader.loadClass()方法显式加载类,隐式装载是在执行程序时出现需要使用类的情况下自动进行加载。
加载
加载是指将类的.class文件读入内存,并在堆区中创建出Class对象的过程。Java虚拟机规范中定义了五种类加载器,分别为:Bootstrap ClassLoader、Extension ClassLoader、System ClassLoader、自定义ClassLoader等。其中Bootstrap ClassLoader是最顶层的类加载器,负责加载系统核心类库,它不能被Java程序直接引用,而是由虚拟机自动加载。
链接
链接分为验证、准备、解析三个过程。
- 验证:验证阶段,会验证类的字节码是否符合Java虚拟机规范。
- 准备:准备阶段,会为静态变量分配内存,并将其初始化为默认值。
- 解析:解析阶段,会将符号引用转换为实际引用。静态绑定和动态绑定就是解析的不同表现。
初始化
初始化阶段,会执行静态变量赋值语句和静态代码块中的代码(静态方法也会被执行和主动调用类中的语句),代表着类的真正实现。
示例1
public class Example01 {
static int num = 0;
static {
num = 10;
}
public static void main(String[] args) {
System.out.println("value of num variable: " + num);
}
}
在初始化Example01类时,会先执行静态块中的代码,将num变量的值赋为10,然后在main函数中输出num的值,输出结果如下:
value of num variable: 10
示例2
public class Example02 {
static int num = 0;
static {
num = 10 / 0;
}
public static void main(String[] args) {
System.out.println("value of num variable: " + num);
}
}
在初始化Example02类时,会执行静态块中的代码,此处除数为0会导致代码报错,运行结果如下:
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: java.lang.ArithmeticException: / by zero
at com.example.Example02.<clinit>(Example02.java:4)
由于在静态初始化中出现异常,导致Example02类的初始化被阻塞,最终造成访问Example02类的异常。
总结
类装载机制是Java程序运行的重要基础,理解它有助于我们更好的理解Java程序运行的原理。同时,我们可以通过ClassLoader来加载自己的.class文件,达到一些自定义的类加载机制,提高程序效率和安全性。