Java 双亲委派机制是什么?类加载器为什么要先委托给父加载器?
下面是一段教学用的模拟面试。
🧑💻 面试官:双亲委派是什么?
🙋♂️ 我:收到类加载请求,先让父加载器加载,父加载不了再自己加载。
🧑💻 面试官:每次都直接找父加载器吗?之前已经加载过的类怎么办?
🙋♂️ 我:要先检查已经加载的类。
🧑💻 面试官:两个插件都有一个同名 User 类,它们就一定是同一个类型吗?先委托父加载器,又会带来什么影响?
本题要同时讲清「查找顺序」和「类的身份」。名字相同,不等于 JVM 眼里就是同一个类。
面试速答(60 秒版)
双亲委派通常指 ClassLoader 默认加载流程中的父委托模型。加载类时,先检查自己是否已经加载过;没有的话,先委托父加载器,父加载器找不到,再尝试自己查找和定义。
这样可以让基础类尽量由一致的上层来源提供,也减少不必要的重复加载。这里的父子是委托关系,不是 Java 类继承关系,也不是同时向两个父加载器请求。
但父优先不是所有场景都不能改变的规则。插件隔离等系统可以设计不同的委托策略,只是必须明确共享类和隔离类的边界。
在 JVM 中,类身份不仅看二进制名称,还看定义它的类加载器。两个加载器分别定义同名类,仍可能是不同类型,不能直接相互转换。

知识点详解:一个类名,沿着谁的查找路径走?
默认加载顺序中,还有“已经加载过”这一步
假设应用请求加载 com.example.User。
默认 loadClass 会先检查已有加载记录;找到就不再重复走完整查找。如果没有,再把请求交给父加载器。父链最终可以到达 JVM 内置的启动类加载机制。
父方找不到时,当前加载器才通过自己的查找逻辑尝试找到类字节并定义类。JDK 25 ClassLoader 文档明确列出了这个顺序。
“父方没找到”也不是“所有错误都吞掉”。类格式错误等失败,不应该一概当成正常缺失继续处理。
父优先有什么实际作用?
假设应用自己的目录也出现一个看起来像基础库的类。如果上层已经提供相应类型,父优先会让应用优先使用上层结果,而不是随意定义另一份。
这有利于共享基础类型和保持一致的来源。不过,安全还涉及包定义限制、模块和访问控制等机制。不能只靠一句“双亲委派保证绝对安全”,就把所有边界解释完。
现代 JDK 通常讨论启动、平台、应用等加载器。本文以 JDK 25 的说明为基准,不把 JDK 8 的扩展类加载器名字混进当前结构。
同名类为什么还能转换失败?
假设插件 A 的加载器定义一份 com.example.User,插件 B 的加载器也定义一份。
虽然包名和类名完全一致,定义加载器却不同,JVM 仍把它们看成不同的类身份。A 的对象不能因为名字一样,就直接变成 B 那个类型的实例。
这里还要区分“发起加载”和“真正定义”。子加载器向父方请求,最后拿到父方定义的类,不等于子加载器又定义了一份。
排错时,除了打印类名,还要看定义加载器。只看异常里的 User 名称,很容易觉得系统莫名其妙。

插件既要隔离,为什么又不能所有类都自己加载?
假设两个插件依赖不同版本的库,可以隔离各自实现,避免互相覆盖。
但如果插件 API 接口也各自加载一份,主程序和插件就可能不认同彼此的类型。调用边界上的接口、参数等共享契约,通常需要由一致的上层来源提供。
因此,委托策略不是“父优先”与“子优先”随意选一个口号。要先划出哪些类必须共享,哪些可以隔离,再设计查找顺序。
释放插件时,也需要考虑旧加载器是否仍被线程、缓存或其他对象保留。换掉文件并不保证旧类立即消失。

面试官继续追问
自定义加载器一定要重写 loadClass 吗?
不一定。如果仍采用默认父委托策略,通常可以把本地查找放进 findClass。只有确实需要改变整体加载顺序,才需要谨慎处理 loadClass 等流程。
双亲委派中的“父”是继承来的父类吗?
不是。一个加载器可以继承 ClassLoader,同时把请求委托给另一个加载器实例。继承关系与委托关系是两条不同的关系。
类加载完成,就一定执行静态初始化了吗?
不一定。加载、链接、初始化是不同阶段,触发初始化还有相应条件。不要把“找到 class 字节”直接说成所有静态代码已经运行。
面试速记卡
- 默认顺序:查已加载 → 父方加载 → 自己查找。
- 父子关系:加载委托,不是类继承,也不是两个父亲。
- 类身份:二进制名称与定义加载器共同决定。
- 插件设计:共享接口与隔离实现分别安排。
- 阶段边界:加载不等于已完成类初始化。
公司面试真题
真题根据求职者公开面经整理,题意经过概括,非逐字原话或公司官方题库;本文为 Sunday 的独立解析。
美团 · Java后端 · 社招
JVM 类加载器和双亲委派怎样工作?(题意整理)
社招一年半面经分享 · 美团部分 ↗
历史面经,面试年份未明确;页面编辑于 2024-07-19