【jvm双亲委派机制详解】appClassLoader虽然打印的内容虽然很多,但它只需要加载target目录下的文件 。
双亲委派机制?虽然基本只有4种类加载器,但这4种类加载器之间是存在一定的关联关系的 。如下图:

文章插图
?加载某个类时会先委托给父加载器寻找目标类,找不到再委托上层父类加载器加载,所有的父类加载器在自己的加载类路径下都找不到目标类,则在自己的类加载路径中寻找并载入目标类 。
?比如上面的TestJDKClassLoader,首先会委托应用程序类加载,应用程序类加载器则委托扩展类加载器加载,扩展类加载器则委托引导类加载器加载,引导类加载器在它的类加载路径下找不到TestJDKClassLoader.class文件,则向下委托扩展类加载器加载,扩展类加载器加载不到则委托应用程序类加载器自己加载,于是应用程序类加载器在target目录下找到并载入了TestJDKClassLoader.class文件 。
我们来看下应用程序类加载器AppClassLoader加载类的双亲委派机制源码,AppClassLoader的loadClass方法最终会调用其父类ClassLoader的loadClass方法,该方法的大体逻辑如下:
我们来看下应用程序类加载器AppClassLoader加载类的双亲委派机制源码,AppClassLoader的loadClass方法最终会调用其父类ClassLoader的loadClass方法,该方法的大体逻辑如下:
我们来看下应用程序类加载器AppClassLoader加载类的双亲委派机制源码,AppClassLoader的loadClass方法最终会调用其父类ClassLoader的loadClass方法,该方法的大体逻辑如下:
- 首先,检查一下指定名称的类是否已经加载过,如果加载过了,就不需要再加载,直接返回 。
- 如果此类没有加载过,那么,再判断一下是否有父加载器;如果有父加载器,则由父加载器加载(即调用parent.loadClass(name, false);).或者是调用bootstrap类加载器来加载 。
- 如果父加载器及bootstrap类加载器都没有找到指定的类,那么调用当前类加载器的findClass方法来完成类加载 。
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{synchronized (getClassLoadingLock(name)) {// First, check if the class has already been loaded// 检查当前类加载器是否已经找到Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {// 有无父类加载器if (parent != null) {c = parent.loadClass(name, false);} else {c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();c = findClass(name);// this is the defining class loader; record the statssun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if (resolve) {resolveClass(c);}return c;}}
为什么要设计双亲委派机制?沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次,保证被加载类的唯一性例子:比如我们自己新建了一个java.lang.String类,我们看能不能加载成功 。
package java.lang;public class String {public static void main(String[] args) {System.out.println("============自己的类加载器====");}}// 执行结果错误: 在类 java.lang.String 中找不到 main 方法, 请将 main 方法定义为:public static void main(String[] args)否则 JavaFX 应用程序类必须扩展javafx.application.Application
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 万字详解JVM,让你一文吃透
- JVM学习笔记——类加载和字节码技术篇
- 详细了解JVM运行时内存
- 【JVM】关于JVM,你需要掌握这些 | 一文彻底吃透JVM系列
- JVM学习笔记——垃圾回收篇
- JVM学习笔记——内存结构篇
- JAVA系列之JVM内存调优
- JDK中自带的JVM分析工具
- 树的邻接矩阵、双亲孩子表示法…… C++ 不知树系列之初识树
- JVM、JDK、JRE你分的清吗