JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)

目录

  • 1.自定义类加载器
  • 2.线程上下文类加载器
  • 3.OSGi模块化
  • 4.JDK9之后的类加载器
  • 5.类加载器总结

JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第1张图片

1.自定义类加载器

⚫ 一个Tomcat程序中是可以运行多个Web应用的,如果这两个应用中出现了相同限定名的类,比如Servlet类,Tomcat要保证这两个类都能加载并且它们应该是不同的类。
⚫ 如果不打破双亲委派机制,当应用类加载器加载Web应用1中的MyServlet之后,Web应用2中相同限定名的MyServlet类就无法被加载了。
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第2张图片
⚫ Tomcat使用了自定义类加载器来实现应用之间类的隔离。
每一个应用会有一个独立的类加载器加载对应的类。JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第3张图片
⚫ 先来分析ClassLoader的原理,ClassLoader中包含了4个核心方法。
⚫ 双亲委派机制的核心代码就位于loadClass方法中。JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第4张图片

源码阅读
⚫ 阅读双亲委派机制的核心代码,分析如何通过自定义的类加载器打破双亲委派机制。
⚫ 打破双亲委派机制的核心就是将下边这一段代码重新实现。

//parent等于null说明父类加载器是启动类加载器,直接调用findBootstrapClassOrNull
//否则调用父类加载器的加载方法
if (parent != null) {
 	c = parent.loadClass(name, false);
 	} else {
 	c = findBootstrapClassOrNull(name);
 }
//父类加载器爱莫能助,我来加载!
if (c == null) 
 	c = findClass(name);

JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第5张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第6张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第7张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第8张图片

2.线程上下文类加载器

JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第9张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第10张图片

⚫ DriverManager属于rt.jar是启动类加载器加载的。而用户jar包中的驱动需要由应用类加载器加载,这就违反了双亲委派机制
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第11张图片
⚫ DriverManage使用SPI机制,最终加载jar包中对应的驱动类。JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第12张图片

SPI中是如何获取到应用程序类加载器的?

⚫ SPI中使用了线程上下文中保存的类加载器进行类的加载,这个类加载器一般是应用程序类加载器。JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第13张图片

⚫ 1、启动类加载器加载DriverManager。
⚫ 2、在初始化DriverManager时,通过SPI机制加载jar包中的myql驱动。
⚫ 3、SPI中利用了线程上下文类加载器(应用程序类加载器)去加载类并创建对象。
⚫ 这种由启动类加载器加载的类,委派应用程序类加载器去加载类的方式,打破了双亲委派机制JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第14张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第15张图片
⚫ 1、启动类加载器加载DriverManager。
⚫ 2、在初始化DriverManager时,通过SPI机制加载jar包中的myql驱动。
⚫ 3、SPI中利用了线程上下文类加载器(应用程序类加载器)去加载类并创建对象JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第16张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第17张图片

3.OSGi模块化

⚫ 历史上,OSGi模块化框架。它存在同级之间的类加载器的委托加载。OSGi还使用类加载器实现了热部署的
功能。
⚫ 热部署指的是在服务不停止的情况下,动态地更新字节码文件到内存中。JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第18张图片

4.JDK9之后的类加载器

JDK8及之前的版本中,扩展类加载器和应用程序类加载器的源码位于rt.jar包中的sun.misc.Launcher.java。

JDK8之后的类加载器
⚫ 由于JDK9引入了module的概念,类加载器在设计上发生了很多变化。
1.启动类加载器使用Java编写,位于jdk.internal.loader.ClassLoaders类中。
2.Java中的BootClassLoader继承自BuiltinClassLoader实现从模块中找到要加载的字节码资源文件。
3. 启动类加载器依然无法通过java代码获取到,返回的仍然是null,保持了统一。
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第19张图片
JDK8之后的类加载器
2、扩展类加载器被替换成了平台类加载器(Platform Class Loader)。
平台类加载器遵循模块化方式加载字节码文件,所以继承关系从URLClassLoader变成了
BuiltinClassLoader,BuiltinClassLoader实现了从模块中加载字节码文件。平台类加载器的存在更多的是
为了与老版本的设计方案兼容,自身没有特殊的逻辑。JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第20张图片

5.类加载器总结

JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第21张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第22张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第23张图片
JVM虚拟机——类加载器(JDK8及以前,打破双亲委派机制)(JDK9之后的类加载器)_第24张图片

你可能感兴趣的:(jvm)