什么是类加载器?
ClassLoader就是类加载器,这个回答是否机智?(鬼脸)
言归正传:还记得在上一篇关于类加载机制的文章中,有一个步骤叫做加载,其中有一个动作就是“通过一个类的全限定名来加载描述此类的二进制流文件”。实现这个动作的代码就叫做类加载器
类与类加载器
两个描述类的二进制流文件相同,这两个类是否就一样?答案是:不一样
判断两个类是否相同的前提是:描述类的二进制流文件相同,并且加载类的类加载器相同
双亲委派系统
对JVM来说总共有两种类加载器:启动类加载器(Bootstrap ClassLoader),这个是使用C++编写的,属于jvm的一部分。另一个是其他类加载器,由java语言实现,并且继承与java.lang.ClassLoader
对于Java开发者来说,总共有三种类加载器:
- 启动类加载器
- 扩展类加载器
- 程序类加载器
启动类加载器,前面已经介绍过一些。启动类加载器主要负责加载存放在
<JAVA_HOME>/lib下面的或者被Xbootclasspath指定的路径中的类库
扩展类加载器,她负责加载<JAVA_HOME>/lib/ext下面的目录
程序类加载器,这个类加载器便是ClassLoader中getSystemClassLoader()方法的返回值,负责加载用户指定路径上的类库。
我们日常程序大部分是由这三种加载器配合使用的。这些加载器之间遵循双亲委派系统的加载模型:
在双亲委派系统模型中,要求除了启动类加载之外的所有加载器都拥有自己的父类加载器。并且这些父子关系不是以继承的关系维持,而是以组合的模式(属于一种设计模式,不懂得小伙伴可以自行查找)形成的。
双亲委派系统的类加载器的工作模式是什么样的呢?
当一个类加载器收到一个类加载请求的时候,首先会把这个请求委派给父类,每一个层次的类加载器都是如此,因此所有的请求最红都会被传递到启动类加载器。在父类反馈自己无法完成这个请求的时候才会让子类来处理这个类加载的任务。
在前面,我们提到过,判断两个类是否相等的条件是:二进制流文件相同,类加载器相同。
正式由于双亲委派模型的这种委派特性,才使得我们整个系统中所使用的基础类保持一致。假设没有这种模型,我们有一个基础类java.lang.Object,在系统的A模块,我们使用ClassLoaderA加载;在系统的B模块我们使用ClassLoaderB加载,就会导致两个模块中的Object不一样,这将会是非糟糕的结果。
下面展示双亲委派模型的实现细节:
protected synchronized Class<?> loadClass(String name,boolean resolve)throws ClassNotFoundException{
//check the class has been loaded or not
Class c = findLoadedClass(name);
if(c == null){
try{
if(parent != null){
c = parent.loadClass(name,false);
}else{
c = findBootstrapClassOrNull(name);
}
}catch(ClassNotFoundException e){
//if throws the exception ,the father can not complete the load
}
if(c == null){
//若父类的类加载器无法加载类,则使用子类的加载器
c = findClass(name);
}
}
if(resolve){
resolveClass(c);
}
return c;
}
---------------------
特别鸣谢:
作者:zhaoenweiex
原文:https://blog.csdn.net/zhaoenweiex/article/details/63289374?utm_source=copy