何为双亲委派
本篇内容介绍了"何为双亲委派"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
双亲委派机制
双亲委派机制是指当一个类加载器收到一个类加载请求时,该类加载器首先会把请求委派给父类加载器。每个类加载器都是如此(递归的去查找),只有在父类加载器在自己的搜索范围内找不到指定类时,子类加载器才会尝试自己去加载。
显然,在介绍双亲委派机制的时候,不得不提ClassLoader。再说ClassLoader之前,我们得先了解下Java的基本知识。
Java是运行在Java的虚拟机(JVM)中的,但是它是怎么就运行在JVM中了呢?我们在IDE中编写的Java源代码被编译器编译成.class
的字节码文件。然后由我们的ClassLoader
负责将这些class文件加载到JVM
中去执行。
JVM中提供了三层的ClassLoader:
Bootstrap ClassLoader(启动类加载器):主要负责加载核心的类库(java.lang.*等),构造Extension ClassLoader
和Application ClassLoader
。
Extension ClassLoader(扩展类加载器):主要负责加载jre/lib/ext
目录下的一些扩展的jar。
Application ClassLoader(应用程序类加载器):主要负责加载应用程序
的主函数类。
最后一个CustomClassLoader(用户自定义类加载器) 是java
编写,用户自定义的类加载器,可加载指定路径的class文件
。
那如果有一个Hello.class
文件是如何被加载到JVM中的呢?
我们简单看一下源码
protected Class> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// 首先检查这个classsh是否已经加载过了Class> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {// c==null表示没有加载,如果有父类的加载器则让父类加载器加载if (parent != null) {c = parent.loadClass(name, false);} else {//如果父类的加载器为空 则说明递归到bootStrapClassloader了//bootStrapClassloader比较特殊无法通过get获取c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {}if (c == null) {//如果bootstrapClassLoader 仍然没有加载过,则递归回来,尝试自己去加载classlong t1 = System.nanoTime();c = findClass(name);sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}
不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理会先检查自己是否已经加载过,如果没有再往上。注意这个过程,直到到达Bootstrap ClassLoader之前,都是没有哪个加载器自己选择加载的。如果父加载器无法加载,会下沉到子加载器去加载,一直到最底层(其实就是递归查找过程),如果没有任何加载器能加载,就会抛出ClassNotFoundException
。
于是,我们就可以很好的总结双亲委派机制的工作流程了:
1、当
Application ClassLoader
收到一个类加载请求时,他首先不会自己去尝试加载这个类,而是将这个请求委派给父类加载器Extension ClassLoader
去完成。2、当
Extension ClassLoader
收到一个类加载请求时,他首先也不会自己去尝试加载这个类,而是将请求委派给父类加载器Bootstrap ClassLoader
去完成。3、如果
Bootstrap ClassLoader
加载失败(在\lib中未找到所需类),就会让 Extension ClassLoader
尝试加载。4、如果
Extension ClassLoader
也加载失败,就会使用Application ClassLoader
加载。5、如果
Application ClassLoader
也加载失败,就会使用Custom ClassLoader
(用户自定义加载器)去尝试加载。6、如果均加载失败,就会抛出
ClassNotFoundException
异常。
双亲委派机制的作用
1、防止重复加载同一个.class
。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
2、保证核心.class
不能被篡改。通过委托方式,不会去篡改核心.class
,即使篡改也不会去加载,即使加载也不会是同一个.class
对象了。不同的加载器加载同一个.class
也不是同一个Class对象。这样保证了Class执行安全。
举个栗子:如果有人想替换系统级别的类:String.java
。篡改它的实现,但是在这种机制下这些系统的类已经被Bootstrap ClassLoader
加载过了,所以并不会再去加载,从一定程度上防止了危险代码的植入。
"何为双亲委派"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!