面试知识库
极高 进阶

双亲委派模型#

一句话答案#

类加载请求先委托父加载器(Bootstrap→Extension→Application),父无法加载时子才加载,防止核心类被篡改。

核心要点

加载顺序: Bootstrap(核心库) → Extension(扩展库) → Application(应用类)

好处: 防止核心类被篡改(如自定义java.lang.String) / 避免类重复加载

打破方式: TCCL(SPI) / 重写loadClass / OSGi / Tomcat

面试回答(2分钟版)

双亲委派模型规定类加载时不会自己先尝试加载,而是把请求逐级委托给父加载器,从 Application ClassLoader 到 Extension ClassLoader 再到 Bootstrap ClassLoader,只有父加载器反馈自己无法加载时,子加载器才会尝试自己加载。这个机制的核心价值有两个:第一是安全性,防止用户自定义一个 java.lang.String 来替换核心类,因为请求一定会先到 Bootstrap ClassLoader 加载 rt.jar 中的原版;第二是避免类的重复加载,保证同一个类在 JVM 中只被加载一次。但有些场景需要打破双亲委派:SPI 机制中核心接口在 Bootstrap 加载但实现类在应用层,Bootstrap 看不到应用层的类,所以通过线程上下文类加载器 TCCL 反向委托给 Application ClassLoader 加载实现类;Tomcat 为了让不同 WebApp 能加载同名类的不同版本,每个 WebApp 有独立的 WebAppClassLoader,优先自己加载而非委托父加载器;还有 OSGi 实现模块化热部署也打破了委派链。

追问与易错

追问方向:

  • “为什么要有双亲委派?”→ 防止核心类被篡改,如自定义 java.lang.String
  • “怎么打破双亲委派?三种方式?”→ ① SPI 机制通过线程上下文类加载器(TCCL)反向委托 ② 重写 loadClass() 方法跳过委派逻辑 ③ OSGi/Tomcat 的 WebAppClassLoader 优先自己加载再委托父加载器
  • “Tomcat 的类加载为什么要打破双亲委派?”→ 不同 WebApp 可能依赖同名类的不同版本

易错点:

  • ❌ “双亲委派不可打破”——SPI/Tomcat/OSGi 都打破了
  • ❌ “委派”理解为”双亲都参与”——其实是单链委派到顶,不是两个父亲