本文主要是介绍classLoader双亲委派机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
java文件会被编译成class文件,而class文件就是通过类加载器classloader进行加载的,java中有BootStrapClassLoader、ExtClassLoader、AppClassLoader三类加载器。
BootStrapClassLoader是使用c++编写的,用于加载java核心类库,是由jvm在启动时创建的,主要是加载JAVA_HOME/jre/lib目录下的类库;
ExtClassLoader用于加载java扩展类库,主要是jre/lib/ext包下的类;
AppClassLoader是应用程序类加载器,用于加载CLASSPATH下我们自己编写的应用程序。
ClassLoader的双亲委派机制是这样的:
当AppClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。
作用:双亲委派是为了安全而设计的,假如我们自定义了一个java.lang.Integer类如下,当使用它时,因为双亲委派,会先使用BootStrapClassLoader来进行加载,这样加载的便是jdk的Integer类,而不是自定义的这个,避免因为加载自定义核心类而造成JVM运行错误。
package java.lang;
/**
* hack
*/
public class Integer {
public Integer(int value) {
System.exit(0);
}
}
初始化这个Integer的构造器是会退出JVM,破坏应用程序的正常进行,如果使用双亲委派机制的话该Integer类永远不会被调用,以为委托BootStrapClassLoader加载后会加载JDK中的Integer类而不会加载自定义的这个,可以看下下面这测试个用例:
public static void main(String... args) {Integer i = new Integer(1);System.err.println(i);}
执行时JVM并未在new Integer(1)时退出,说明未使用自定义的Integer,于是就保证了安全性。
这篇关于classLoader双亲委派机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!