【JVM类加载】类的初始化和类加载器双亲委托机制(【JVM深度解析】类初始化与类加载器双亲委托机制详解)
原创在Java虚拟机(JVM)中,类加载和初始化是程序运行的基础。本文将详细介绍类的初始化过程以及类加载器的双亲委托机制。
一、类的初始化
类的初始化是类加载过程的最后一步,它是在类被使用的时候进行的。初始化阶段是执行类构造器
类的初始化过程如下:
- 如果类还没有被加载和链接,首先触发类的加载和链接过程。
- 初始化类的时候,首先执行其超类的
()方法,递归进行。 - 执行类构造器
()方法,对类变量进行初始化。
下面是一个易懂的示例,展示了类的初始化过程:
public class SuperClass {
static {
System.out.println("SuperClass init!");
}
public static int value = 123;
}
public class SubClass extends SuperClass {
static {
System.out.println("SubClass init!");
}
}
public class Test {
public static void main(String[] args) {
System.out.println(SubClass.value);
}
}
运行上述代码,输出于是为:
SuperClass init!
123
可以看到,在初始化SubClass时,首先初始化了其超类SuperClass。
二、类加载器
类加载器是JVM的一个重要组成部分,它负责将Java类库中的类加载到JVM中。类加载器本身也是类,负责加载其他类。在JVM中,类加载器可以分为以下三种类型:
- 引导类加载器(Bootstrap ClassLoader):用于加载Java核心库,无法被Java程序直接引用。
- 扩展类加载器(Extension ClassLoader):用于加载扩展库(java.ext.dirs)中的类。
- 应用类加载器(Application ClassLoader):用于加载当前应用的类路径(classpath)中的类。
三、双亲委托机制
双亲委托机制是类加载器的一个关键特性,它要求除了顶层的引导类加载器外,其余的类加载器都应当遵循以下原则:
当类加载器接收到一个类的加载请求时,首先不会自己尝试去加载这个类,而是将其委托给父类加载器去完成。只有当父类加载器反馈自己无法完成这个类的加载请求(即找不到该类或其父类加载器无法加载该类)时,才会自己尝试去加载该类。
双亲委托机制的优势在于:
- 避免重复加载:当父类加载器已经加载了一个类时,子类加载器无需再次加载,从而避免了重复加载。
- 保护程序平安:防止核心API被随意篡改,例如java.lang.String类。
下面是一个易懂的示例,展示了双亲委托机制的应用:
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader classLoader = Class.forName("java.lang.String").getClassLoader();
System.out.println(classLoader);
ClassLoader parentClassLoader = classLoader.getParent();
System.out.println(parentClassLoader);
ClassLoader rootClassLoader = parentClassLoader.getParent();
System.out.println(rootClassLoader);
}
}
运行上述代码,输出于是为:
null
sun.misc.Launcher$ExtClassLoader@1540e19d
sun.misc.Launcher$BootstrapClassLoader@3d4e0a89
可以看到,String类的加载器是Bootstrap ClassLoader,它的父类加载器是Extension ClassLoader,而Extension ClassLoader的父类加载器是Bootstrap ClassLoader。
四、总结
本文详细介绍了JVM中的类初始化过程以及类加载器的双亲委托机制。类初始化是类加载过程的最后一步,它通过执行类构造器