机制定义
如果一个类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。
类加载器
Java是运行在Java的虚拟机(JVM)中的,但是它是怎么就运行在JVM中了呢?我们在IDE中编写的Java源代码被编译器编译成.class的字节码文件。然后由我们得ClassLoader负责将这些class问价加载到JVM中去执行。
JVM中提供了三层的ClassLoader:
1) 引导类加载器(Bootstrap class loader):它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader。它负责将<Java_Runtime_Home>/lib下面的核心类库或-Xbootclasspath选项指定的jar包加载到内存中。由于引导类加载器涉及到虚拟机本地实现细节,开发者无法直接获取到启动类加载器的引用,所以不允许直接通过引用进行操作。
(2) 扩展类加载器(Extensions class loader):该类加载器在此目录里面查找并加载 Java 类。扩展类加载器是由Sun的 ExtClassLoader(sun.misc.Launcher$ExtClassLoader)实现的。它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。它负责将< Java_Runtime_Home >/lib/ext或者由系统变量-Djava.ext.dirs指定位置中的类库加载到内存中。开发者可以直接使用标准扩展类加载器。
(3) 系统类加载器(System class loader):系统类加载器是由 Sun的 AppClassLoader(sun.misc.Launcher$AppClassLoader)实现的。它负责将系统类路径java -classpath或-Djava.class.path变量所指的目录下的类库加载到内存中。开发者可以直接使用系统类加载器。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。
双亲委派机制的作用
1、防止重复加载同一个类
。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
2、保证核心类
不能被篡改。这样保证了执行安全。
双亲委派机制的缺点
1 因为类加载器受到加载范围的限制,在某些情况下父类加载器无法加载到需要的文件。
2 无法支持多版本
3 性能有影响,因为每次都要向上调用
Tomcat 为什么要破坏双亲委派机制?
1 因为Tomcat启动是一个jvm,所以需要 webapp
中的 class
和 lib
,要相互隔离,不然会出现一个应用中加载的类库会影响另一个应用的情况(同一个类库版本的问题,类同名的问)。
jar项目为什么要破坏双亲委派机制?
1 jar项目有一套自己管理依赖包的方式,需要定制加载器来处理这些jar