类加载器分析

时间:2022-12-29 09:28:25

首先,我们要明确类加载器的作用

1、加载类;

2、类加载器和类本身确立其在java虚拟机中的唯一性。


每一个类加载器,都有一个独立的类名称空间。因此,java.util.date与java.sql.data是两个不同的类。

加载器的种类:

从虚拟机角度来看,只有两种:

1、启动类加载器(BootStrap ClassLoader),由C++实现,是虚拟机自身的一部分;

2、所有其他的加载器,由java语言实现,独立于虚拟机外部,并且全都继承java.lang.ClassLoader。


从开发人员角度分,主要是四种:

1、BootStrap ClassLoader:负责将存放在java_Home\lib目录中的,或者被-Xbootclasspath参数所指定的路径中的,

并且是虚拟机识别的(如rt.jar,名字不符合的类库即使放在这路径下面也不会被加载)类库加载到虚拟机内存中。

启动类加载器无法被java程序直接引用。

2、Extension ClassLoader:扩展类加载器,负责加载java_Home/lib/ext目录中的,或者被java.ext.dirs系统变量所指定的

路径中的所有类库。该加载器可以被直接使用。

3、Application ClassLoader:应用程序加载器,这个加载器是ClassLoader中的getSystemClassLoader()方法的返回值,也叫作系统类加载器。

负责加载用户类路径(ClassPath)上所指定的程序,开发者可以直接使用。该加载器为程序中默认的类加载器。

4、自定义类加载器。


双亲委派模型:

类加载器分析

除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。这里加载器的父子关系一般不使用继承,而是使用组合关系来复用父加载器的代码。

在jdk1.2中引入了该机制,但它并不是一个强制性的约束模型,而是一种推荐的加载器的实现方式。


工作流程:

一个类加载器得到类加载的请求之后,首先他不会自己去尝试加载这个类,而是把请求委派给父类加载器去完成,因此所有的类加载请求最终都会

传送到顶层的启动类加载器中,只有当父类加载器反馈自己无法完成这个加载请求,子加载器才会尝试自己去加载。


好处:

1、java类随类加载器的一起举杯了一种带有优先级的层次关系。使得类的辨别容易,不会混乱,不会因为用户写的类与系统类库冲突(若重名则虽然可以正常编译

,但不能被加载运行,虚拟机会抛出SecurityException异常)。

2、保证java程序运行的稳定性。实现双亲委派模型的代码在java.lang.ClassLoader中的loadClass方法。

先检查是否已经被加载过,若没有加载则调用父加载器的loadClass方法,若父加载器为空,默认使用启动类加载器作为父类。

如果父类加载失败,抛出ClassNotFound异常后,在调用自己的findClass方法。