讲师中心 微信公众号
AI工具推荐 视频效率加速

详解Java中的类加载器层级_Bootstrap、Extension与AppClassLoader

星杰小哥_3667

星杰小哥_3667

发布时间:2026-02-18 12:13:20

|

252人浏览过

|

来源于php中文网

原创

new ClassLoader() 不能加载 java.lang.String,因为核心类由 BootstrapClassLoader 强制加载,自定义类加载器双亲委派后仍无法覆盖,且 JVM 会校验包名并拒绝加载 java.* 类。

详解java中的类加载器层级_bootstrap、extension与appclassloader

为什么 new ClassLoader() 不能加载 java.lang.String

因为所有由 JVM 直接识别的核心类(如 java.lang.*、java.util.*)都由 BootstrapClassLoader 加载,它用 C++ 实现、没有 Java 对象引用,也不在类加载器链中。你写的自定义 ClassLoader 子类哪怕重写了 loadClass(),默认也会先委托给父加载器——最终走到 BootstrapClassLoader;但它不认你的字节码,也不会把控制权交回来。

常见错误现象:NoClassDefFoundError 或 ClassNotFoundException 明明 class 文件存在,却报找不到 String、Object 等基础类。

  • 不要试图用自定义类加载器去“覆盖”或“替换”核心类——JVM 会直接拒绝加载
  • 若需隔离类(比如插件系统),应确保插件 jar 不含 java.* 或 javax.* 包,否则启动时就失败
  • 想绕过双亲委派加载自己的 java.util.ArrayList?不行。JVM 在加载阶段会校验包名,java.* 包强制走 Bootstrap

ExtensionClassLoader 的路径在哪、现在还用不用

它的标准扩展目录是 $JAVA_HOME/jre/lib/ext(Java 8 及以前),但 Java 9+ 已移除 ExtensionClassLoader,相关机制被模块系统(java.base 等命名模块)取代。如果你在 JDK 11+ 上打印 ClassLoader.getSystemClassLoader().getParent().getParent(),结果是 null——不是 bug,是设计删除。

使用场景:老项目迁移时遇到 ExtClassLoader 相关日志或代码,要意识到它已失效。

立即学习“Java免费学习笔记(深入)”;

Java注释规范Skills
Java注释规范Skills

当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。

下载
  • JDK 8 中可通过 -Djava.ext.dirs=/path/to/ext 指定额外扩展目录,但该参数在 JDK 9+ 被废弃并报错
  • 替代方案:用 --module-path + --add-modules 加载模块,或直接把依赖放到 classpath
  • 别再往 lib/ext 放 jar——现代 JDK 启动会忽略,甚至抛 SecurityException

AppClassLoader 加载失败的三个典型原因

这是你写 new Object() 时背后实际工作的类加载器,也是绝大多数 ClassNotFoundException 发生的地方。它只管 -cp 或 CLASSPATH 下的路径,不查 jar 内部嵌套、不递归扫描子目录。

常见错误现象:明明 jar 在 classpath 里,却报找不到某个类;或 IDE 跑得通,命令行 java -jar 就失败。

  • java -cp myapp.jar Main 不会自动解压 jar 里的依赖——myapp.jar 内部的 lib/xxx.jar 不会被 AppClassLoader 扫到
  • 用 java -jar 时,MANIFEST.MF 中的 Class-Path: 条目只支持相对路径,且不支持通配符(* 是 JDK 6+ 特性,但仅限于 java -cp 场景,对 -jar 无效)
  • IDE 默认把 Maven 依赖全加进运行 classpath,但打包成 fat-jar 或分发时没处理好依赖路径,就会出现“本地 OK,服务器炸了”

自定义类加载器必须重写 findClass() 而不是 loadClass()

因为 loadClass() 默认实现做了双亲委派逻辑,直接重写它容易破坏委托顺序,导致核心类加载异常或重复加载。正确做法是让 loadClass() 走默认流程,只在 findClass() 里专注“从哪读字节码、怎么转成 Class 对象”。

性能影响:每次 findClass() 都要读文件或网络,没缓存的话会显著拖慢反射调用或动态代理生成。

  • 务必在 findClass(String name) 中把 name 转为路径(如 com.foo.Bar → com/foo/Bar.class),再读取字节码
  • 调用 defineClass() 前,检查字节码是否为空或长度为 0,否则抛 ClassFormatError
  • 如果需要热替换,注意 ClassLoader 实例和它加载的类对象强绑定,旧类无法卸载,除非整个加载器被回收——而 GC 是否回收取决于是否有强引用

类加载器层级不是树形结构而是链式委托,Bootstrap 和 Extension 在现代 JDK 中已大幅弱化,真正可控、可调试、易出错的,始终是 AppClassLoader 及其子类。别花时间猜哪个加载器该加载什么,先看 getClass().getClassLoader() 输出谁,再顺着它的 getParent() 往上捋——大部分问题,卡在第三层就结束了。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

相关专题

更多
bootstrap框架介绍
bootstrap框架介绍

本专题整合了bootstrap框架相关介绍,阅读专题下面的文章了解更多详细内容。

745

2026.03.18

bootstrap安装教程
bootstrap安装教程

本专题整合了bootstrap安装相关教程,阅读专题下面的文章了解更多详细操作教程。

199

2026.03.18

Java Maven专题
Java Maven专题

本专题聚焦 Java 主流构建工具 Maven 的学习与应用,系统讲解项目结构、依赖管理、插件使用、生命周期与多模块项目配置。通过企业管理系统、Web 应用与微服务项目实战,帮助学员全面掌握 Maven 在 Java 项目构建与团队协作中的核心技能。

4160

2025.09.15

Java Maven/Gradle 构建与依赖管理合集
Java Maven/Gradle 构建与依赖管理合集

系统讲解 Java 项目构建工具的使用与进阶配置,涵盖 Maven 的 POM 文件结构、生命周期(clean/compile/package/install/deploy)与插件机制、依赖范围(compile/provided/test/runtime)与传递依赖管理、多模块聚合与继承、私有 Nexus 仓库发布,以及 Gradle 的 Groovy / Kotlin DSL 语法、Task 自定义与增量构建、依赖版本目录(Versi

389

2026.05.09

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

6819

2023.08.02

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1698

2024.03.01

c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

549

2023.09.22

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

40

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn