文章目录
一、类加载器
从Java虚拟机的角度来讲,只存在两种不同的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另一种就是所有其他的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全都继承自抽象类 java.lang.ClassLoader
。
-
启动类加载器(Bootstrap ClassLoader): 负责加载存放在
<JAVA_HOME>\lib
目录中的核心类库,如rt.jar
、resources.jar
等(或者被-Xbootclasspath
参数所指定的路径中的,并且是虚拟机识别的类库)。这个加载器是 C++ 编写的,随着JVM启动。 -
扩展类加载器(Extension ClassLoader): 负责加载
<JAVA_HOME>\lib\ext
目录中的类库,(同样也可以用java.ext.dirs
系统变量来指定路径)。 -
应用程序类加载器(Application ClassLoader): 负责加载用户类路径 classpath 上所有的 jar 包和 .class 文件。
-
自定义类加载器: 可以支持一些个性化的扩展功能。
二、类与类加载器
对于任意一个类,都需要由加载它的类加载器和这个类本身一同确立其在Java虚拟机中的唯一性,每一个类加载器,都拥有一个独立的类名称空间。
这句话可以表达得更通俗一些:比较两个类是否“相等”,只有在这两个类是由同一个类加载器加载的前提下才有意义,否则,即使这两个类来源于同一个Class文件,被同一个虚拟机加载,只要加载它们的类加载器不同,那这两个类就必定不相等。
这里所指的“相等”,包括代表类的Class对象的 equals()
方法、isAssignableFrom()
方法、isInstance()
方法的返回结果,也包括使用 instanceof
关键字做对象所属关系判定等情况。
三、双亲委派模型
为了避免类的重复加载,确保一个类的全局唯一性,以及保护程序安全,防止核心API被随意篡改,JVM会采用双亲委派模型进行加载,双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应当有自己的父类加载器。
双亲委派模型的工作过程是: 如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类