双亲委派模型

双亲委派模型

JVM中的ClassLoader通常采用双亲委派模型,要求除了启动类加载器外,其余的类加载器都应该有自己的父级加载器。这里的父子关系是组合而不是继承,工作过程如下:

  1. 一个类加载器接受到类加载请求后,首先搜索它的内建加载器定义的所有“具名模块”
  2. 如果找到了合适的模块定义,将会使用该加载器来加载
  3. 如果class没有在这些加载器定义的具名模块中找到,那么将会委派给父级加载器,直到启动类加载器
  4. 如果父级加载器反馈它不能完成加载请求,比如在它的搜索路径下找不到这个类,那么子的类加载器才自己来加载
  5. 在类路径下找到的类将成为这些加载器的无名模块

双亲委派模型说明:

  1. 双亲委派模型对于保证Java程序的稳定运作很重要
  2. 实现双亲委派的代码在java.lang.ClassLoader的loadClass()方法中,如果自定义类加载器的话,推荐覆盖实现findClass()方法
  3. 如果有一个类加载器能加载某个类,称为定义类加载器,所有能成功返回该类的Class的类加载器都被称为初始类加载器
  4. 如果没有指定父加载器,默认就是启动加载器
  5. 每个类加载器都有自己的命名空间、命名空间由该类加载器及其所有父加载器所加载的类构成,不同的命名空间,可以出现类的全路径名相同的情况

(单根不可能出现,但是多根就会出现)

  1. 运行时包由同一个类加载器的类构成,决定两个类是否属于同一个运行时包,不仅要看全路径名是否一样,还要看定义类加载器是否相同。只有属于同一个运行时包的类才能实现相互包内可见。

破坏双亲委派模型

❤:双亲模型有个问题:父加载器无法向下识别子加载器加载的资源

(api提供前端和应用程序、web自己使用、spi供应商扩展的接口)

(不能只找父,也要父找子)

为了解决这个问题,引入了线程上下文类加载器,可以通过Thread的setContextLoader()进行设置

❤:另外一种典型情况就是实现热替换,比如OSGI的模块化热部署,它的类加载器就不再是严格按照双亲委派模型,很多可能就在平级的类加载器中执行了

---- The end of this article ----