类加载器及双亲委派模型

今天说下java的类加载器以及双亲委派模型

-- 简单介绍     我们先说类加载器:类加载器是通过一个类的全限定名来获取描述这个类的二进制字节流的代码模块。类加载器虽然只是实现类的加载动作,但它的实际作用并不是只在类的加载阶段。对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在java虚拟机中的唯一性。每一个类加载器都有一个独立的类名称空间。比如说我们要比较两个类相等,只有在这两个是同一类加载器加载的前提下才有意义,如果说这两个来自于同一个class文件,被同一个虚拟机加载,只要加载他们的类加载器不同,那这两个类就不相等。

--类加载器的不同分类

从java虚拟机的角度来看,类加载器可以分为两种,第一种是启动类加载器 (bootstrap classLoader) ,这个类加载器都是由C++语言实现的,是java虚拟机的一部分;另一种就是所有其他的类加载器,这些类加载器都是由java语言实现的,独立于虚拟机外部,并且全都继承自抽象类ClassLoader。

从java开发者角度来看,类加载器还能划分的更细致一些,

       1.启动类加载器,这个我们刚才说过,这个类加载器负责将存放在<java_home>lib目录中的,或者被 -Xbootclasspath参数指定的路径中的,并且虚拟机能够识别的,将会把类库加载到虚拟机内存中。

              --说明:JDK中的常用类都是由启动类加载器加载的,比如String,Object,List ,启动类 Main class 也是由启动类加载器加载的。

       2.扩展类加载器,Extension ClassLoader 它负责加载<java_home>libext目录下的类库,或者是 java.ext.dirs指定路径下的。开发者能够使用这种类加载器。

       3.还有一种是我们常用的,应用程序类加载器 Appliaction ClassLoader 这个类加载器是ClassLoader中的方法getSystemClassLoader的返回值,所以我们一般称他为系统类加载器。它负责加载用户类路径上的所指定的类库,我们能够直接使用这个类加载器。如果应用程序中没有自定义自己的类加载器,一般情况下这个就是程序中默认的类加载器。所以我们的应用程序一般都是由这三种类加载器相互配合进行加载的。如果有必要,还可以加入自己定义的类加载器。然后我们再说下 类加载器的双亲委派模型

--双亲委派模型的结构

       是这样的:首先最上层结构是 启动类加载器 然后第二层是扩展类加载器 再往下是应用程序类加载器,在之后就是我们自定义的类加载器。

       双亲委派模型要求除了启动类加载器之外的所有类加载器都要有父类加载器。类加载器之间的父子关系并不是使用继承的方式来实现的,而是用的组合的方式。

双亲委派模型是在JDK1.2被引入的,它不是一个强制性的约束模型

--双亲委派模型的工作过程是这样的,当一个类加载器收到了类加载的请求时,它首先不会自己去尝试加载这个类,而是会把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,那么我们也可以发现,类加载处理每个类加载请求的时候,请求都会到启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求时,子加载器才会尝试自己去加载。

--使用双亲委派模型有个显而易见的好处就是java类随着它的类加载器一起具备了一种带有优先级的层次关系。比如说Object类,它存放在rt.jar包中,所以无论哪个类加载器这个类,最终都会委派给启动类加载器进行加载,因为Object类在各种类加载器并存的情况下都是同一个类。我们自己也可以编写一个Object类,同一个包下的,它是可以正常编译的,但是不能被加载运行。

--双清委派模型的代码实现是在ClassLoader中的loadClass方法之中,大致过程是这样的:

       先判断这个类有没有被加载过了,若没有加载则调用父加载器的loadClass方法,如果父加载器为空,则直接使用启动类加载器作为父加载器加载类资源,如果父类加载失败,抛出ClassNotFoundException 异常后,再调用自己的findClass方法进行加载

这就是loadClass方法的大致过程。

一个入行不久的Java开发,越学习越感觉知识太多,自身了解太少,只能不断追寻
原文地址:https://www.cnblogs.com/fengtingxin/p/11872424.html