Java类加载器算是一个老生常谈的问题
什么是类加载器?
这就是类加载器
把class文件的byte[] 加载成Class对象,加载到JVM里面
1 | class MyClassLoader extends ClassLoader { |
为什么要弄这么都类加载器,还有层级关系,而不一股脑都加载到JVM里呢
1.定义一个层级就有优先级了,可以先加载啥,后加载啥,防止例如java.lang.String 根加载器的类,被第三方jar包冲掉
2.按需加载,需要的再加载,体现了java语言的动态特点
梳理结构
BootstrapClassLoader
加载路径:%JAVA_HOME%\lib
System.out.println(System.getProperty("sun.boot.class.path"));
底层C++编写,不属于java类,根本没有对应的java类名
根类加载器,也叫引导类加载器、启动类加载器。
主要加载rt.jar charsets.jar
就是jdk自带的类
sun.misc.Launcher$ExtClassLoader
加载路径:%JAVA_HOME%\lib\ext
System.out.println(System.getProperty("java.ext.dirs"));
扩展类加载器
sun.misc.Launcher$AppClassLoader
加载路径:%CLASS_PATH%
System.out.println(System.getProperty("java.class.path"));
应用类加载器
双亲委派
简单说,ClassLoader是一个抽象类
1.提供了一个loadClass()
方法
2.有一个parent
字段
作用:就是加载类的时候,先自下往上搜索一边。
都没有,再用自身这个类加载器去加载。
1 | protected Class<?> loadClass(String name, boolean resolve) |
1.如果要实现自己的类加载器且不破坏双亲委派模型,只需要继承ClassLoader类并重写findClass方法。
2.如果要实现自己的类加载器且破坏双亲委派模型,则需要继承ClassLoader类并重写loadClass,findClass方法。
上下文类加载器
1 | //加载驱动程序 |
这里面第1行按前面里理解 肯定是应用加载器
第二行DriverManager
是数据java基础类库 由跟加载器加载
那么在DriverManager如何获取到应用加载器呢?
1 | Thread.currentThread().getContextClassLoader(); |