JVM类加载器!
JVM类加载器!
月伴飞鱼Bootstrap引导类加载器
引导类加载器也被称为启动类加载器或根类加载器
- 指
BootstrapClassLoader
。引导类加载器使用C++语言实现,是JVM自身的一部分
- 主要负责将
<JAVA_HOME>\lib
路径下的核心类库- 或
-Xbootclasspath
参数指定的路径下的jar
包加载到内存中。
Extension拓展类加载器
位于
HotSpot
源码目录中的sun.misc.Launcher$ExtClassLoader
位置。它主要负责加载
<JAVA_HOME>\lib\ext
目录下
- 或者由系统变量
-Djava.ext.dir
指定位路径中的类库。
Application系统类加载器
位于
HotSpot
源码目录中的sun.misc.Launcher$AppClassLoader
位置。它负责加载系统类路径
java -classpath
- 或
-D java.class.path
指定路径下的类库,也就是classpath
路径。该类加载器是程序的默认类加载器
- 可以通过
ClassLoader.getSystemClassLoader()
方法可以直接获取到它。
自定义类加载器
如果需要自定义类加载器,只需要继承
ClassLoader
类
- 但继承
ClassLoader
需要自己重写findClass()
方法并编写加载逻辑在自定义
ClassLoader
的子类时,会有两种做法:
重写
loadClass()
方法重写
findClass()
方法
loadClass()
最终调用的还是findClass()
方法
如果想打破双亲委派模型,那么就重写整个
loadClass
方法如果不想打破双亲委派模型,那么只需要重写
findClass
方法
线程上下文类加载器
很多服务提供者接口(
Service Provider Interface,SPI
),这些接口允许第三方为它们提供实现
- 如常见的
SPI
有JDBC、JNDI
等这些
SPI
的接口属于Java
核心库,一般存在rt.jar
包中
- 由启动类加载器(
Bootstrap
)加载- 而
SPI
的第三方实现代码则是作为Java
应用所依赖的jar
包被存放在classpath
路径下。由于
SPI
接口中的代码需要加载第三方实现类并调用其相关函数
- 但
SPI
的核心接口类是由启动类加载器(Bootstrap
)加载的,Bootstrap
加载器无法直接加载SPI
的实现类。SPI提供了一种动态的服务发现机制(约定),只要第三方在编写实现类时
- 在工程内新建一个
META-INF/services/
目录并在该目录下创建一个与服务接口名称同名的文件- 那么在程序启动的时候,就会根据约定去找到所有符合规范的实现类
- 然后交给线程上下文类加载器进行加载处理。
线程的上下文类加载器默认设置的就是系统类加载器(
System
)。
JDK1.8和1.9中类加载器有哪些不同
JDK 1.9 引入 Jigsaw 模块化系统(Project Jigsaw),对类加载器进行了调整。
JDK 1.8 | JDK 1.9 及之后 | 变化 |
---|---|---|
扩展类加载器(Extension ClassLoader) | 平台类加载器(Platform ClassLoader) | 负责加载 JDK 模块化系统中的非核心模块 |
应用类加载器(Application ClassLoader) | 应用类加载器(Application ClassLoader) | 负责加载应用程序的 classpath |
JDK 1.9 类加载器结构:
1 | Bootstrap ClassLoader |
JDK 版本 | 主要类加载器 | 变化 |
---|---|---|
JDK 1.8 及之前 | Bootstrap、Extension、Application | 使用 Extension ClassLoader 加载 lib/ext |
JDK 1.9 及之后 | Bootstrap、Platform、Application | Extension ClassLoader 被 Platform ClassLoader 取代 |