vlambda博客
学习文章列表

JVM:类加载器·双亲委派模型

点击蓝字关注我们

JVM:类加载器·双亲委派模型

JVM:类加载器·双亲委派模型

我达到目标的惟一的力量就是我的坚持精神。巴斯德

引导语

类加载器顾名思义,用于实现类的加载动作。

类加载器应用:OSGi、程序热部署、代码加密等。

类加载器之间的关系:双亲委派模型。

1
类与类加载器

比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个Java虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。

这里所指的“相等”,包括代表类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返回结果,也包括了使用instanceof关键字做对象所属关系判定等各种情况。

2
三层类加载器


启动类加载器(Bootstrap ClassLoader)

负责加载存放在<JAVA_HOME>\lib目录,或者被-Xbootclasspath参数所指定的路径中存放的。(C++语言实现)

扩展类加载器(Extension ClassLoader)

负责加载<JAVA_HOME>\lib\ext目录中,或者被java.ext.dirs系统变量所指定的路径中所有的类库。(Java代码实现sun.misc.Launcher$ExtClassLoader)

扩展:JDK 9之后,这种扩展机制被模块化带来的天然的扩展能力所取代。

应用程序类加载器(Application ClassLoader)

负责加载用户类路径(ClassPath)上所有的类库。(Java代码实现sun.misc.Launcher$AppClassLoader)

由于应用程序类加载器是ClassLoader类中的getSystem-ClassLoader()方法的返回值,所以有些场合中也称它为“系统类加载器”。

3
双亲委派模型

JVM:类加载器·双亲委派模型

除了启动类加载器外,都应有父类加载器。

关系:一般不是继承的关系,而是组合的关系复用父加载器的代码。

原理:

如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到最顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去完成加载。

4
破坏双亲委派模型

1. 如何在父加载器加载的类中,去调用子加载器去加载类?

此处引入线程上下文类加载器(Thread  Context ClassLoader),通过java.lang.Thread类的setContext-ClassLoader()方法进行设置,如果创建线程时还未设置,它将会从父线程中继承一个,如果在应用程序的全局范围内都没有设置过的话,那这个类加载器默认就是应用程序类加载器。

Java中涉及SPI的加载基本都在采用该方式,如:JNDI、JDBC、JCE、JAXB和JBI。

SPI实现方式:

JDK(6)提供了java.util.ServiceLoader类,以META-INF/services中的配置信息,辅以责任链模式。

JDBC举例:

JDBC的Driver接口定义在JDK中,其实现有数据库的各个厂商提供。DriverManager类中要加载各个实现了Driver接口的类统一进行管理,Driver类位于JAVA_HOME中jre/lib/rt.jar中,应该由Bootstrap类加载器进行加载,而各个Driver的实现类位于各个服务商提供的jar包中。根据类加载机制,当被加载的类引用了另外一个类时,虚拟机就会使用装载第一个类的类加载器装在被引用的类,也就是说应该使用Bootstrap类加载器去加载各个厂商提供的Driver类。但是,Bootstrap类加载器只负责加载JAVA_HOME中jre/lib/rt.jar中所有的class,所以需要由子类加载器去加载Driver的实现类,这就破坏了双亲委派模型。

2. OSGi如何通过类加载器实现热部署(“即插即用”)?

OSGi实现模块化热部署的关键是它自定义的类加载器机制的实现,每一个程序模块(OSGi中称为Bundle)都有一个自己的类加载器,当需要更换一个Bundle时,就把Bundle连同类加载器一起换掉以实现代码的热替换。

说到OSGi,这里想到了“Spring DM”Spring动态模型。

3. Tomcat类加载器为什么破坏双亲委派?

tomcat是个web容器,有可能需要部署多个应用程序,不同的应用程序有可能会以来同一个第三方类库不同的版本。

Tomcat类加载图

JVM:类加载器·双亲委派模型

5
扩展

1. OSGI类加载器

JVM:类加载器·双亲委派模型

OSGI 框架根据 Bundle 的 MANIFEST.MF 文件中描述的数据信息进行解析处理 Bundle 间的依赖关系。


推荐阅读:



扫码关注更多精彩
JVM:类加载器·双亲委派模型
JVM:类加载器·双亲委派模型