天天看点

jvm类加载器双亲委派机制浅析

首先来了解几个概念:

类加载:

    概念:虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验--转换解析--初始化,最终形成能被java虚拟机直接使用的java类型,就是jvm的类加载机制。

    类加载包含了以下过程:加载--验证--准备--解析--初始化--使用--卸载

jvm类加载器双亲委派机制浅析

类加载器:

    首先,什么是类加载器?

概念:把类加载阶段中"通过一个类的全限定名来获取描述此类的二进制流"这个动作放到jvm外部去实现,以便让应用程序自己决定如何去获取所需要的类。实现这个动作的代码模块被称为"类加载器"。

分类:(针对hot spot而言,因为mrp,maxine的虚拟机完全是由java实现)

站在java虚拟机的角度上讲,只存在两种不同的类加载器。启动类加载器 和 其他类加载器。

    启动类加载器:由c++实现,是虚拟机自身的一部分.

    其他类加载器:由java实现,独立于虚拟机外部,全继承于抽象类java.lang.classloader.

站在java开发人员的角度上讲  ,分为三种

  *启动类加载器(bootstrap classloader):  前面已经提到,主要加载<java_home>/lib目录中 ,或被-xbootclasspath参数指定路径中的jar包。

  *扩展类加载器(extension classloader):由sun.misc.launcher$extclassloader来实现。主要加载<java_home>/lib/ext 目录中 ,或被java.ext.dirs系统变量指定路径中所有类库。

  *应用程序类加载器(application classloader):由sun.misc.launcher$appclassloader来实现。由于这个类加载器是classloader中getsystemclassloader()方法返回值,所以也叫系统类加载器。负责加载用户类路径上(classpath)指定的类库,是开发过程中默认的加载器,开发者可直接使用。

jvm类加载器双亲委派机制浅析

说到这里,不得不提一下"双亲委派模型(parent delegation model)"。如上图。

双亲委派模型:描述类加载器之间的层次关系的就是双亲委派模型。

双亲委派模型要求出顶层的 启动类加载器 外,其余类加载器都应有自己的父类加载器。

加载器之间的父子关系不是靠继承的关系实现,是使用组合关系的关系来复用父类加载器的代码。

双亲委派模型工作过程:若一个类加载器收到类加载请求,他首先不会自己尝试去加载这个类,而是把这个请求委派给父类加载器去完成,每一层类加载器都是如此,所以所有请求都会传送到顶层的bootstrap classloader,只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围没找到),子加载器才会自己尝试去加载。

使用双亲委派模型好处:

java类以及它的类加载器一起具备了一种带有优先级的层次关系。如 java.lang.object(它在rt.jar之中)。

    首先我们要知道一点,同一个类 被不同的 类加载器 加载成两个类之后,这两个类是不同的。

如果java.lang.object类被不同的类加载器加载很多次,jvm中存在了多个不同的object类,那么java类型体系中最基础的行为也无从保证,应用程序会一片混乱(we know,all the class extends from java.lang.object,如果object存在多个品种,那绝对是灾难)。

    相反,使用了双亲委派模型,无论哪个类加载器去加载,都会委派到boorstrap classloader进行加载,保证了object在各个类加载器环境中,都是同一个类。

  再提一点双亲委派模型的工作机制,以类 a 为例,a如果以application classloader方式来加载,application classloader委派给extension classloader,再到bootstrap classloader.

然而,bootstrap classloader管理范围内(<java_home>/lib目录中 ,或-xbootclasspath参数指定路径中的jar包)没查到类a,那么就让最初请求的类加载器,application classloader来加载

at last,提一点,双亲委派模型 在jvm成长史上被重大破坏过三次,但是 双亲委派模型确实不错,还是像小强一样的活了下来

原文链接:http://www.cnblogs.com/xiaoliu66007/p/3376219.html

继续阅读