孤芳不自赏

玩命工作,就是年轻时最好的生活。

类加载器——双亲委派模型。

        从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全部继承自抽象类java.lang.ClassLoader。

        从Java开发人员的角度来看,类加载器还可以划分得更细致一些,绝大部分Java程序都会使用以下3种系统提供的类加载器。

启动类加载器(Bootstrap ClassLoader)

        这个类加载器负责将存放在<JAVA_HOME>\lib目录中,或者被-Xbootclasspath参数所指定的路径中的,并且是虚拟机识别的(仅按照文件名识别,如rt.jar,名字不符合的类库即使放在lib目录中也不会被加载)类库加载到虚拟机内存中。启动类加载器无法被Java程序直接引用,用户在编写自定义类加载器时,如果需要把加载请求委派给引导类加载器,那直接使用null代替即可,下面代码所示为java.lang.ClassLoader.getClassLoader()方法的代码片段。


扩展类加载器(Extension ClassLoader)

        这个加载器由sun.misc.Launcher $ExtClassLoader实现,它负责加载<JAVA_HOME>\lib\ext目录中的,或者被java.ext.dirs系统变量所指定的路径中所有类库,开发者可以直接使用扩展类加载器。

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

        这个类加载器由sun.misc.Launcher $AppClassLoader实现。由于这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,所以一般也称为他为系统类加载器。他负责加载用户类路径(ClassPath)上所指定的类库,开发者可以直接使用这个类加载器,如果应用程序中没有自定义过自己的类加载器,一般情况下这个就是程序中默认的类加载器。

        我们的应用程序都是由这3种类加载器互相配合进行加载的,如果有必要,还可以加入自己定义的类加载器。这些类加载器之间的关系一般如下图所示。


        上图中展示的类加载器之间的这种关系,称为类加载器的双亲委派模型(Parents Delegation Model)。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器,这里类加载器之间的父子关系一般不会以继承(Inheritance)的关系来实现,而是都使用组合(Composition)关系来复用父加载器的代码。

        类加载器的双亲委派模型在JDK 1.2期间被引入并被广泛应用于之后几乎所有的Java程序中,但他并不是一个强制性的约束模型,而是Java设计者推荐给开发者的一种类加载器实现方式。

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

        使用双亲委派模型来组织类加载器之间的关系。有一个显而易见的好处就是Java类随着他的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,他存放在rt.jar之中,无论哪一个类加载要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.Object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。如可以尝试去编写一个与rt.jar类库中已有类重名的Java类,将会发现可以正常编译,但永远无法被加载运行。

        双亲委派模型对于保证Java程序的稳定运作很重要,但他的实现却分厂简单,实现双亲委派的代码都集中在java.lang.ClassLoader的loaderClass()方法之中,如下面代码所示,逻辑清晰易懂:先检查是否已经被加载过,若没有加载则调用父加载器的loadClass()方法,若父加载器为空则默认使用启动类加载器作为父加载器。如果父类加载失败,抛出ClassNotFoundException异常后,再调用自己的findClass()方法进行加载。


阅读更多
文章标签: jvm
个人分类: JVM
上一篇类加载器——类与类加载器。
下一篇类加载器——破坏双亲委派模型。
想对作者说点什么? 我来说一句

jvm 类加载机制 双亲委派模型

2018年04月17日 359KB 下载

java 类加载器 class loader

2009年04月10日 114KB 下载

类加载器与Tomcat

2010年08月16日 60KB 下载

18.类加载器.doc

2011年08月30日 1.32MB 下载

boot.js

2014年04月14日 3.97MB 下载

tomcat类加载器

2012年12月11日 18KB 下载

java 类加载器 加密

2014年10月17日 6KB 下载

没有更多推荐了,返回首页

关闭
关闭