类加载流程图

-
加载:在硬盘上查找并通过IO读入字节码文件至JVM虚拟机方法区,同时在堆中创建class对象
-
验证:校验字节码文件的正确性
-
准备:为类的的静态变量分配内存,并将其初始化为默认值。此阶段仅为静态变量(static)分配内存;对于final static修饰的变量,编译时即分配内存;也不会分配实例变量的内存
-
解析:把类中的符号引用转换为直接引用
-
初始化:对类的静态变量初始化为指定值,执行静态代码块
加载细节

在创建引导类加载器这里,创建的同时会传经扩展类加载器和应用类加载器;这样讲是因为在创建启动器实例Launcher时,它的构造方法中会创建另外两个加载器
//Launcher类的构造方法
public Launcher() {
//扩展类加载器
Launcher.ExtClassLoader var1;
try {
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
//应用类加载器
try {
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
....省略SecurityManager安全管理机制的代码
}
-
引导类加载器:负责加载jre/libz目录下的核心类库,比如rt.jar
-
扩展类加载器:负责加载jre/lib/ex目录中的JAR包
-
应用类加载器:负责加载classPath路径/类路径下的class字节码文件,主要是自己写的那些类编译好的类
双亲委派机制存在的意义:
- 避免类的重复加载:当父加载器已经加载的了该类,子classLoader就没必要再加载一次,保证被加载类的唯一性
- 沙箱安全机制:自己定义的 类和源码中的类一样时,是没办法加载进去的,这样避免了源码API被随意篡改
三个类加载器的类检测顺序:应用类->扩展类->引导类;检测是通过ClassLoader类中的loadClass()查找,在所有的类都没有查找到后,会通过classLoader中的findClass()去加载,但是ClassLoader中的findClass是没有实现的,所以会由子类 URLClassLoader去加载类
//抽象类ClassLoader中的findClass方法
protected Class<?> findClass(String name) throws ClassNotFoundException {
throw new ClassNotFoundException(name);
}
本文详细介绍了Java类加载过程,包括加载、验证、准备、解析和初始化五个阶段,并阐述了类加载器的工作原理及双亲委派机制的意义。

被折叠的 条评论
为什么被折叠?



