类加载器学习
1、类加载器作用
类加载器的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
类缓存:标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不管JVM垃圾回收机制可以回收这些Class对象
2、类加载器的类型
类加载器的作用时用来把类(Class)装载进内存中。JVM规范定义了如下类型的类加载器。
引导类加载器(BootstrapClassLoader):用C++编写的,是JVM自带的类加载器,负责Java平台的核心库,用来装载核心类库。该加载器无法直接获取
扩展类加载器(ExtentionClassLoader):负责jre/lib/ext目录下的jar或者-D java.ext.dirs指定目录下的jar包装入工作库
系统类加载器(AppClassLoader):负责java-classpath或者-D java.class.path所指的目录下的类与jar包装入工作,是最常用的类加载器
BootstrapClassLoader核心jar包就是rt.jar包以本人MacOS系统寻找rt.jar包寻找
拓展类加载器jar包位置定位(MacOS系统)
3、代码获取加载器
3.1、Demo1
/**
* @Author: Ambition
* @Description TODO
* @Date: 2021/9/12 10:33 下午
* @Version 1.0
*/
public class ClassLoadTest02 {
public static void main(String[] args) {
// 获取系统类加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
// 获取拓展类加载器
ClassLoader parent = systemClassLoader.getParent();
System.out.println(parent);
// 获取根加载器 因为bootstrap由C++标写我们获取不到这个加载器
ClassLoader bootstrap = parent.getParent();
System.out.println(bootstrap);
}
}
执行结果如下(个人使用不同的jdk下面的输出结果也不一样)
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1e80bfe8
null
3.2、Demo2
package com.xmaven.test;
/**
* @Author: Ambition
* @Description TODO
* @Date: 2021/9/12 10:33 下午
* @Version 1.0
*/
public class ClassLoadTest02 {
public static void main(String[] args) {
try {
// 测试当前类是哪个加载器所加载的
ClassLoader cl1 = Class.forName("com.xmaven.test.ClassLoadTest02").getClassLoader();
// 系统类加载器加载
System.out.println(cl1);
// 测试JDK内置的类是由谁加载的
ClassLoader cl2 = Class.forName("java.lang.Object").getClassLoader();
// 引导类加载器加载
System.out.println(cl2);
} catch (ClassNotFoundException e) {
System.out.println("ClassNotFoundException!!!");
e.printStackTrace();
}
}
}
输出结果如下:
sun.misc.Launcher$AppClassLoader@18b4aac2
null
3.3、系统类加载器获取加载的路径
/**
* @Author: Ambition
* @Description TODO
* @Date: 2021/9/12 10:33 下午
* @Version 1.0
*/
public class ClassLoadTest02 {
public static void main(String[] args) {
// 如何获取系统类加载器可以加载的路径 不同的环境输出的结果不一样,结果太长不输出演示了
System.out.println(System.getProperty("java.class.path"));
}
}
3.4、类加载双亲委派模型(面试)
所谓的类加载双亲委派模型也就是一种类的加载机制,也就是说有一定的流程来加载这个类
比如说有一个A.Class这个类
我们现在希望类加载器加载这个A.Class
执行流程:
系统类加载器(AppClassLoader)不会主动加载这个类,它首先会问一下它的父类加载器--扩展类加载器(ExtentionClassLoader)你有没有加载这个A.Class
如果扩展类加载器(ExtentionClassLoader)没有加载,它会询问它的父类--引导类加载器(BootstrapClassLoader)你有没有加载这个A.Class
如果都没有加载这个A.Class,则会有一个自顶向下的顺序尝试加载这个类
注意点:BootstrapClassLoader只负责rt.jar,不负责加载用户放在类路径的A.Class
此时都没人加载的话,引导类加载器会把这个加载类的任务交给它的孩子-扩展类加载器,此时这个扩展类加载器会查看当前类是否位于这个扩展类加载器负责的范围内,如果不位于它的范围之内,引导类加载器会把这个加载类的任务交给它的孩子-系统类加载器,系统类加载器发现这个A.Class位于它的当前的类路径下,就会进行加载这个A.Class
检查机制:自底向上检查类是否被加载
加载机制:自顶向下尝试加载类
评论区