1、 ClassLoader:具体的作用就是将class文件加载到jvm虚拟中去,程序就可以正确运行了
但是,jvm启动的时候,并不会一次性加载所有的class文件,而是根据需要去动态加载。
2、 java 类加载流程:
java语言系统自带有三个类加载器:
Bootstrap ClassLoader (引导类加载器)最顶层的加载类,主要加载核心类库,%JRE_HOME%\lib 下边的rt.jar、resources.jar 和class等
E:\Java\jdk1.8.0_152\jre\lib\resources.jar;
E:\Java\jdk1.8.0_152\jre\lib\rt.jar;
E:\Java\jdk1.8.0_152\jre\lib\sunrsasign.jar;
E:\Java\jdk1.8.0_152\jre\lib\jsse.jar;
E:\Java\jdk1.8.0_152\jre\lib\jce.jar;
E:\Java\jdk1.8.0_152\jre\lib\charsets.jar;
E:\Java\jdk1.8.0_152\jre\lib\jfr.jar;E:\Java\jdk1.8.0_152\jre\classes
这些全是JRE目录下的jar包或者是class文件
Extention ClassLoader (延伸类加载器)扩展类加载器,加载%JRE_HOME%\lib\ext下的jar包或class文件
Appclass Loader也称作SystemAppClass 加载当前应用的classpath的所有类
加载顺序
a、Bootstrap ClassLoader
b、Extention ClassLoader
c、Appclass Loader
Launcher :sun.misc.Launcher,它是java虚拟机的应用入口
其中:
private static String bootClassPath = System.getProperty("sun.boot.class.path"); //最顶层的类加载器
var1 = Launcher.ExtClassLoader.getExtClassLoader(); //延伸类加载器
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1); //App应用加载器
Thread.currentThread().setContextClassLoader(this.loader); //设置AppClassLoader为线程上下文类加载器,这个文章后面部分讲解
3、ClassLoader 的源码
private final ClassLoader parent; //类加载的parent 也是一个ClassLoader
private static ClassLoader scl;
//创建ClassLoader对象的时候将parant添加上去
this(checkCreateClassLoader(), getSystemClassLoader()); //没有的情况调用getSystemClassLoader(); 方法
scl = l.getClassLoader(); //默认的情况通过Launcher的getClassLoader()来获取到
---------其实也就是AppClassLoader为默认的父类加载
由上可见:
一个ClassLoader对象的parent:
a、由外部类创建ClassLoader时直接指定一个ClassLoader为parent
b、由getSystemClassLoader()方法生成 ------也就是sun.misc.Laucher通过getClassLoader()
------也就是AppClassLoader
直白的说,一个classLoader创建的时如果没有指定parent,那么它的parent默认就是AppClassLoader
c、
var1 = Launcher.ExtClassLoader.getExtClassLoader();
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
AppClassLoader的parent是ExtClassLoader,ExtClassLoader的parent是null;
d、ExtClassLoader的父加载器为null,但是Bootstrap CLassLoader却可以当成它的父加载器 ------为什么那
Bootstrap ClassLoader是由C++编写的,他本身就是虚拟机的一部分
e、JVM初始化sun.misc.Launcher并创建ExtensionClassLoader 和 AppClassLoader实例,并且将ExtensionClassLoader设置为 AppClassLoader的父加 器
另外补充: private final ClassLoader parent;
final修改的字段在赋值之后便不能修改,这句话的理解:final修饰的字段只能赋值一次
private 结合 final 能实现在改类中肯定会实现其属性的实例,并且只有一次
也就是在classLoader中有且只有一次属性赋值,并且只有一次赋值
4、 双亲委托
a、某个class请求加载 自身的classLoader --->父类的classLoader ----->AppClassLoader(向上委托方式) ------>缓存中查找
b、AppClassLoader---->ExtClassLoader(向上委托方式) ----->缓存中查找
c、ExtClassLoader---->Bootstrap(向上委托方式)----->缓存中查找
----------------------------------------------------------------向下查找方向
d、Bootstrap ClassLoader 规定的路径 sun.mic.boot.class下查找 ------- %JRE_HOME%\lib 下
e、ExtClassLoader的规定路径java.ext.dirs 下查找 -------- %JRE_HOME%\lib\ext下的jar包或class文件
f、AppClassLoader的路径 java.class.path下查找 ------- classpath下的所有类
5、 应用:
自定义class、加密class 使得仅仅只有自己可以执行class文件
Thread.currentThread().setContextClassLoader(this.loader); //获取classLoader之间的关联