Skip to Content
面试题库Jvm[面试题] 双亲委派是什么?

[面试题] 双亲委派是什么?

📖 版块 A:知识讲解版 (温故知新)

  • 核心定义:当一个类加载器收到类加载请求时,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成。每一个层次的类加载器都是如此,因此所有的加载请求最终都应该传送到顶层的启动类加载器(Bootstrap ClassLoader)中。只有当父类加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

  • 类加载器层级(自顶向下)

    1. Bootstrap ClassLoader(启动类加载器):由 C++ 实现,负责加载 Java 核心库(JAVA_HOME/lib 目录,如 rt.jar)。
    2. Extension ClassLoader(扩展类加载器):负责加载 Java 的扩展库(JAVA_HOME/lib/ext 目录)。
    3. Application ClassLoader(系统类加载器):负责加载用户类路径(ClassPath)下的所有类库,是程序中的默认类加载器。
    4. Custom ClassLoader(自定义类加载器):用户根据需求自行定义的加载逻辑。
  • 双亲委派的作用

    1. 安全性(防止核心 API 被篡改):避免用户自己写一个 java.lang.String 类来替代 JDK 自带的类,从而导致安全隐患。
    2. 唯一性:保证同一个类在程序中只被加载一次,确保了程序运行的稳定性。

🎤 版块 B:面试实战版 (高手逐字稿)

Q:什么是双亲委派机制?

💬 高手逐字稿

简单来说,双亲委派机制就是:当一个类加载器需要加载一个类时,它会先“尽孝道”,把请求转发给父类加载器去处理。只有当父类加载器说“我处理不了”时,子加载器才会尝试自己加载。

这个过程可以分为三个阶段:首先是向上委托。当 Application ClassLoader 收到请求,它先看缓存里有没有,没有就给 Extension ClassLoader,一直到最顶层的 Bootstrap ClassLoader。其次是顶层尝试加载。Bootstrap ClassLoader 会在它的搜索范围(比如 rt.jar)里找,找到了就返回。最后是向下派发。如果顶层没找到,抛出 ClassNotFoundException,下层的加载器才会依次尝试从自己的路径中搜索并加载。

为什么要这么大费周折呢? 核心价值在于“安全”和“稳定”。通过这种机制,Java 核心类库(如 java.lang.Object、String 等)始终由顶层的启动类加载器加载,这保证了核心 API 的全局唯一性。试想一下,如果没这个机制,我自己写一个 java.lang.Integer 类并注入进去,那 JVM 内部的逻辑可能就直接崩溃了。

不过,这里有一个容易被忽略的细节,就是双亲委派并不是“铁律”,在很多场景下是会被打破的。 最典型的例子就是 SPI 机制,比如 JDBC。JDBC 的接口定义在 JDK 核心库中,是由 Bootstrap ClassLoader 加载的,但具体的实现类(如 MySQL 驱动)是在 ClassPath 下的。根据双亲委派,核心库的类是拿不到第三方实现的。为了解决这个问题,Java 引入了 Thread Context ClassLoader(线程上下文类加载器),让父加载器请求子加载器去加载类,这实际上是逆向违背了双亲委派。

此外,像 Tomcat 这种容器为了实现 Web 应用间的类隔离,或者像 OSGi 这种为了实现热部署,都会自定义类加载器逻辑,通过先找子类再找父类的方式打破双亲委派,以实现更灵活的加载策略。

最后更新于:
⏱️

登录后开始阅读

当前 MVP 版本只开放邮箱密码登录注册。完成登录后即可进入面试题内容。

还没有账号?先去注册