一:什么是类加载器
1.类加载器(ClassLoader)是Java虚拟机提供给应用程序去实现获取类和接口字节码数据的技术。 类加载器只参与加载过程中的字节码获取并加载到内存这一部分。
二:类加载器分类(jdk8及之前)
- java虚拟机底层代码源码实现的:保证java程序运行中基础类被正确地加载,比如java.lang.String,确保其可靠性。启动类加载器
- java代码中实现的:继承自抽象类ClassLoader。扩展类加载器,应用类加载器
三:启动类加载器
- 启动类加载器(Bootstrap ClassLoader)是由Hotspot虚拟机提供的、使用C++编写的类加载器。
- 默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等
- 通过启动类加载器去加载用户jar包:
- 放入jre/lib下进行扩展:不推荐,尽可能不要去更改JDK安装目录中的内容,会出现即时放进去由于文件名不匹配的问题也不会正常地被加载
- 使用参数进行扩展:推荐,使用-Xbootclasspath/a:jar包目录/jar包名 进行扩展
四:扩展类加载器和应用类加载器
-
扩展类加载器和应用程序类加载器都是JDK中提供的、使用Java编写的类加载器
-
它们的源码都位于sun.misc.Launcher中,是一个静态内部类。继承自URLClassLoader。具备通过目录或者指定jar包将字节码文件加载到内存中。
扩展类加载器:
- 默认加载Java安装目录/jre/lib/ext下的类文件。
- 通过扩展类加载器去加载用户jar包:
- 放入/jre/lib/ext下进行扩展:不推荐,尽可能不要去更改JDK安装目录中的内容
- 使用参数进行扩展:推荐,使用-Djava.ext.dirs=jar包目录 进行扩展,这种方式会覆盖掉原始目录,可以用;(windows):(macos/linux)追加上原始目录
应用类加载器:
- 加载classpath下的类文件和应用使用的类
四:双亲委派机制
- 双亲委派机制指的是:自底向上查找是否加载过,再由顶向下进行加载。
- 作用:
- 保证类加载的安全性通过双亲委派机制,让顶层的类加载器去加载核心类,避免恶意代码替换JDK中的核心类库,比如java.lang.String,确保核心类库的完整性和安全性。
- 避免重复加载,双亲委派机制可以避免同一个类被多次加载,上层的类加载器如果加载过类,就会直接返回该类,避免重复加载。
五:打破双亲委派机制
1.自定义类加载器
- 继承ClassLoader,重写loadClass()方法
- 自定义加载器的父加载器是默认是应用类加载器
2.线程上下文类加载器(使用了SPI机制+线程上下文类加载器)
- JDBC案例:DriverManager属于rt.jar是启动类加载器加载的。而用户jar包中的驱动需要由应用类加载器加载,这就违反了双亲委派机制。
3.OSGi模块化
- OSGi模块化框架。它存在同级之间的类加载器的委托加载。
JDK9之后的类加载器
- 扩展类加载器被替换成了平台类加载器(Platform Class Loader)。
- 平台类加载器遵循模块化方式加载字节码文件,所以继承关系从URLClassLoader变成了 BuiltinClassLoader,BuiltinClassLoader实现了从模块中加载字节码文件。