类加载子系统
加载阶段
- 引导类加载器(
BootstrapClassLoader)BootstrapClassLoader这个类是用c/c++编写的,嵌套在JVM内部- 它用来加载Java的核心库(
JAVA_HOME/jre/lib/rt.jar or resources.jar or sun.boot.class.path) 路径下的内容 - 不继承
java.java.lang.ClassLoader,没有父加载器
- 扩展类加载器(
ExtClassLoader)Java语言编写,由sun.misc.Launcher$ExtClassLoader实现- 派生于
ClassLoader类 - 父类加载器为启动类加载器
- 从jdk的安装目录
jre/lib/ext子目录下加载类库,如果用户创建的jar放在此目录下,也由ExtClassLoader加载
- 系统类加载器
Java语言编写,由sun.misc.Launcher$AppClassLoader- 派生于
ClassLoader类 - 父类加载器为启动类加载器
- 负责加载环境变量
classpath或系统属性 - 该类加载是程序中默认的类加载器
- 自定义类加载器
- 这个主要交由开发者自行实现,继承
ClassLoaderorURLClassLoader - 如果继承
URLClassLoader可以避免自己实现findClass方法和获取字节码流
- 这个主要交由开发者自行实现,继承
下面是获取类加载器具体代码
// 系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
// jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
System.out.println(systemClassLoader);
// 扩展类加载器
ClassLoader extClassLoader = systemClassLoader.getParent();
// jdk.internal.loader.ClassLoaders$PlatformClassLoader@682a0b20
System.out.println(extClassLoader);
// 试图获取引导类加载器,结果是无法获取到.
ClassLoader bootStrapClassLoader = extClassLoader.getParent();
// null
System.out.println(bootStrapClassLoader);
// 用户自定义类的加载器使用的是系统类加载器 systemClassLoader
ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
// jdk.internal.loader.ClassLoaders$AppClassLoader@63947c6b
System.out.println(classLoader);
// 获取引导类加载器可加载jar包的路径
for (URL url : Launcher.getBootstrapClassPath().getURLs()) {
System.out.println(url.getPath());
}
// 获取扩展类加载器可加载的jar包的路径
String property = System.getProperty("java.ext.dirs");
for (String path : property.split(";")) {
System.out.println(path);
}
双亲委派机制
- 如果一个类加载器收到类加载请求,会把这个请求委托给父类加载器执行
- 如果父类加载器还存在父类则向上委托,最终达到系统类加载器
- 如果父类可以自己完成加载则成功返回,否则交给子类加载器加载
链接阶段
验证(verify)
- 文件格式验证
- 元数据验证
- 字节码验证
- 符号引用验证码
准备(prepare)
- 为变量分配内存并设置初始值,即零值
final修饰的常量再准备阶段会显示初始化
解析(resolve)
- 将常量池内的符号饮用转换为直接引用
- 解析动作主要包括:
- 类、接口、字段、类方法、接口方法、方法类型等,对应常量池中的:
CONSTANT_CLASS_INOF、CONSTANT_FILEDREF_INOF等信息。
- 类、接口、字段、类方法、接口方法、方法类型等,对应常量池中的:
初始化阶段
以下过程全部按照声明变量的顺序进行赋值
- 父类静态变量和静态代码块赋值
- 自身的静态变量和静态代码块赋值
- 父类成员变量和构造函数赋值
- 自身变量构造函数赋值