共计 2391 个字符,预计需要花费 6 分钟才能阅读完成。
这篇文章主要讲解了“Java 的双亲委派模型是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着丸趣 TV 小编的思路慢慢深入,一起来研究和学习“Java 的双亲委派模型是什么”吧!
双亲委派模型的工作流程是:如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把请求委托给父加载器去完成,依次向上,因此,所有的类加载请求最终都应该被传递到顶层的启动类加载器中,只有当父加载器在它的搜索范围中没有找到所需的类时,即无法完成该加载,子加载器才会尝试自己去加载该类。
双亲委派机制:
1、当 AppClassLoader 加载一个 class 时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器 ExtClassLoader 去完成。
2、当 ExtClassLoader 加载一个 class 时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给 BootStrapClassLoader“` 去完成。
3、如果 BootStrapClassLoader 加载失败(例如在 $JAVA_HOME/jre/lib 里未查找到该 class),会使用 ExtClassLoader 来尝试加载;
4、若 ExtClassLoader 也加载失败,则会使用 AppClassLoader 来加载,如果 AppClassLoader 也加载失败,则会报出异常 ClassNotFoundException。
ClassLoader 源码分析:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public Class ? loadClass(String name)throws ClassNotFoundException {
return loadClass(name, false);
}
protected synchronized Class ? loadClass(String name, boolean resolve)throws ClassNotFoundException {
Class c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClass0(name);
}
} catch (ClassNotFoundException e) {
c = findClass(name);
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
双亲委派模型意义:
系统类防止内存中出现多份同样的字节码
保证 Java 程序安全稳定运行
什么是双亲委派模型?
简单说,类加载器就是根据指定全限定名称将 class 文件加载到 JVM 内存,转为 Class 对象。如果站在 JVM 的角度来看,只存在两种类加载器:
启动类加载器(Bootstrap ClassLoader):由 C ++ 语言实现(针对 HotSpot), 负责将存放在 JAVA_HOME \lib 目录或 -Xbootclasspath 参数指定的路径中的类库加载到内存中。
其他类加载器:由 Java 语言实现,继承自抽象类 ClassLoader。如:扩展类加载器(Extension ClassLoader):负责加载 JAVA_HOME \lib\ext 目录或 java.ext.dirs 系统变量指定的路径中的所有类库。应用程序类加载器(Application ClassLoader)。负责加载用户类路径(classpath)上的指定类库,我们可以直接使用这个类加载器。一般情况,如果我们没有自定义类加载器默认就是用这个加载器。
双亲委派模型工作过程
双亲委派模型工作过程是:如果一个类加载器收到类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器完成。每个类加载器都是如此,只有当父加载器在自己的搜索范围内找不到指定的类时(即 ClassNotFoundException),子加载器才会尝试自己去加载。
为什么需要双亲委派模型?
为什么需要双亲委派模型呢?假设没有双亲委派模型,试想一个场景:
黑客自定义一个 java.lang.String 类,该 String 类具有系统的 String 类一样的功能,只是在某个函数稍作修改。比如 equals 函数,这个函数经常使用,如果在这这个函数中,黑客加入一些“病毒代码”。并且通过自定义类加载器加入到 JVM 中。此时,如果没有双亲委派模型,那么 JVM 就可能误以为黑客自定义的 java.lang.String 类是系统的 String 类,导致“病毒代码”被执行。
而有了双亲委派模型,黑客自定义的 java.lang.String 类永远都不会被加载进内存。因为首先是最顶端的类加载器加载系统的 java.lang.String 类,最终自定义的类加载器无法加载 java.lang.String 类。
或许你会想,我在自定义的类加载器里面强制加载自定义的 java.lang.String 类,不去通过调用父加载器不就好了吗? 确实,这样是可行。但是,在 JVM 中,判断一个对象是否是某个类型时,如果该对象的实际类型与待比较的类型的类加载器不同,那么会返回 false。
举个简单例子:
ClassLoader1、ClassLoader2 都加载 java.lang.String 类,对应 Class1、Class2 对象。那么 Class1 对象不属于 ClassLoad2 对象加载的 java.lang.String 类型。
感谢各位的阅读,以上就是“Java 的双亲委派模型是什么”的内容了,经过本文的学习后,相信大家对 Java 的双亲委派模型是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是丸趣 TV,丸趣 TV 小编将为大家推送更多相关知识点的文章,欢迎关注!