双亲委派机制

末蓝、 2022-11-15 03:56 365阅读 0赞

JVM提供了三种类加载器,分别为启动类加载器(Bootstrap Classloader)、扩展类加载器(Extention Classloader)和应用程序类加载器(Application Classloader)。其中启动类加载器是使用C/C++语言实现的,是虚拟机自身的一部分;其它的类加载器,都是由Java语言实现的,独立存在于虚拟机外部,并且全部继承自抽象类java.lang.ClassLoader。

  • 启动类加载器:虚拟机内置加类加载器,通常表示为null,没有父加载器。负责加载JAVA_HOME/lib目录中的类库,或通过-Xbootclasspath参数指定路径中被虚拟机认可的类库
  • 扩展类加载器:是在类sun.misc.Launcher$ExtClassLoader中以Java代码的形式实现的。负责加载JAVA_HOME/lib/ext目录中的类库,或通过java.ext.dirs系统变量加载指定路径中的类库
  • 应用程序类加载器:这个类加载器由sun.misc.Launcher$AppClassLoader来实现。由于应用程序类加载器是ClassLoader类中getSystem-ClassLoader()方法的返回值,所有有些场合中也成它为”系统类加载器”。负责加载用户路径classpath上面的类库。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21hZ2kxMjAx_size_16_color_FFFFFF_t_70

除了JVM提供的三种默认的类加载器,用户也可以通过继承java.lang.ClassLoader实现自定义类加载器。

双亲委派

JVM通过双亲委派机制对类进行加载。双亲委派机制指一个类在收到类加载请求后,不会尝试自己加载这个类,而是把该类加载请求向上委派其父类去完成,其父类在接收到该类加载请求后又会将其委派个自己的父类,以此类推,这样所有的类加载请求都被向上委派到启动类加载器中。若父类加载器在接收到类加载请求后发现自己也无法加载该类(通常原因是该类的Class文件在父类的类加载路径中不存在),则父类会将该信息反馈给子类并向下委派子类加载器加载该类,知道该类被成功加载,若找不到该类,则JVM会抛出ClassNotFound异常。

双亲委派类加载机制的类加载流程如下

1、将自定义加载器挂载到应用程序类加载器

2、应用程序类加载器将类加载请求委托给扩展类加载器

  1. 3、扩展类加载器将类加载请求委托给启动类加载器
  2. 4、启动类加载器在加载路径下查找并加载Class文件,如果未找到目标Class文件,则交由扩展类加载器加载
  3. 5、扩展类加载器在加载路径下查找并加载Class文件,如果未找到目标Class文件,则交由应用程序类加载器加载
  4. 6、应用程序类加载器在加载路径下查找并加载Class文件,如果未找到目标Class文件,则交由自定义类加载器加载
  5. 7、在自定义类加载器下查找并加载用户指定目录下的Class文件,如果在自定义加载路径下未找到目标Class文件,则抛出ClassNotFound异常。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L21hZ2kxMjAx_size_16_color_FFFFFF_t_70 1

双亲委派机制的核心是保障类的唯一性和安全性。例如,在加载rt.jar包中的java.lang.Object类时,无论是哪个类加载器加载这个类,最终都将类加载请求委托给启动类加载器加载,这样就保证了类加载的唯一性。如果在JVM中存在包名和类名相同的两个类,则该类将无法被加载,JVM无法完成该类加载流程。

源码查看

ClassLoader类中loaderClass方法

  1. /**
  2. * 加载规范的二进制类名称
  3. * 默认实现按照以下方式查找类
  4. *
  5. * <ol>
  6. * <li><p> 调用findLoadedClass(String)方法检查该类是否已经被加载</p></li>
  7. *
  8. * <li><p> 在父类加载器上调用loadClass方法。
  9. * 如果父级是null ,则使用内置到虚拟机中的类加载器。 </p></li>
  10. *
  11. * <li><p> 调用findClass(String)方法找到该类</p></li>
  12. * </ol>
  13. *
  14. * <p> 如果类在上述步骤中找到, 且resolve标识为true
  15. * 则该方法将调用resolveClass(Class)方法对所生成的Class对象.
  16. *
  17. * <p> 鼓励ClassLoader子类覆盖findClass(String) ,而不是这种方法</p>
  18. *
  19. * <p> 除非被覆盖,否则该方法在整个类加载过程中同步getClassLoadingLock方法的结果
  20. *
  21. * @param 类名称
  22. * @param 装载标识
  23. * @return 结果class类
  24. * @throws 如果没有找到该类,抛出ClassNotFoundException异常
  25. *
  26. */
  27. protected Class<?> loadClass(String name, boolean resolve)
  28. throws ClassNotFoundException
  29. {
  30. // 使用同步锁,加载类名称,避免多线程重复加载
  31. synchronized (getClassLoadingLock(name)) {
  32. // 第一步,检查该类是否已经类加载
  33. Class<?> c = findLoadedClass(name);
  34. // 如果未加载
  35. if (c == null) {
  36. long t0 = System.nanoTime();
  37. try {
  38. // 其父加载器不为null
  39. // 则说明父加载器为应用程序类加载器或扩展类加载器
  40. if (parent != null) {
  41. // 交由其父加载器加载该class类
  42. c = parent.loadClass(name, false);
  43. } else {
  44. // 若父加载器为null,则说明其父加载器为启动类加载器
  45. // 交由启动类加载器加载该类
  46. c = findBootstrapClassOrNull(name);
  47. }
  48. } catch (ClassNotFoundException e) {
  49. // 捕获查找过程中的异常信息
  50. }
  51. if (c == null) {
  52. // 如果各层父类加载器都未找到该类
  53. // 则调用findClass方法来自己加载该类
  54. long t1 = System.nanoTime();
  55. c = findClass(name);
  56. // this is the defining class loader; record the stats
  57. sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
  58. sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
  59. sun.misc.PerfCounter.getFindClasses().increment();
  60. }
  61. }
  62. if (resolve) {
  63. resolveClass(c);
  64. }
  65. return c;
  66. }
  67. }

发表评论

表情:
评论列表 (有 0 条评论,365人围观)

还没有评论,来说两句吧...

相关阅读

    相关 双亲委派机制

    什么是双亲委派机制? JVM加载字节码文件是按需加载,只有用到该类时才会加载字节码文件到内存中生成Class的对象,加载字节码文件采用的是双亲委派机制。 工作原理

    相关 双亲委派机制

    Java虚拟机对Class文件采用的是按需加载的方式,也就是说当需要使用该类时,才会加载该类的对象到内存当中生成class对象。而且加载某个类的class文件时,Java虚拟机

    相关 双亲委派机制

    JVM提供了三种类加载器,分别为启动类加载器(Bootstrap Classloader)、扩展类加载器(Extention Classloader)和应用程序类加载器(App

    相关 双亲委派机制

    > 双亲委派机制 > JVM类加载器是有亲子层级结构的,如下图 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shado

    相关 双亲委派机制总结

    预定义类加载器和双亲委派机制 1. JVM预定义的三种类型类加载器: 启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将

    相关 双亲委派机制

    ![这里写图片描述][70] 上图中展示的类加载器之间的这种层次关系,称为类加载器的双亲委派模型。双亲委派模型除了顶层的启动类加载器之外,其余的类加载器都应当有自己的父类加

    相关 双亲委派机制

    一 点睛 Java虚拟机对class文件采用的是按需加载的方式,也就是说当需要使用该类时才会将它的class文件加载到内存生成class对象。而且加载某个类的class文