java类加载机制通过双亲委派模型和字节码验证双重保障,确保java.*等核心类只能由bootstrap classloader加载且不可篡改,非法加载直接抛securityexception,类唯一性由“加载器+全限定名”决定。

Java 类加载机制通过双亲委派模型和字节码验证两道硬性防线,从源头杜绝核心类库(如 java.lang.String、java.util.ArrayList)被篡改的可能。它不依赖运行时检查,而是在类加载的第一步就切断非法路径。
启动类加载器独占 java.* 类定义权
所有以 java.、javax. 开头的类,JVM 强制规定只能由 C++ 实现的 Bootstrap ClassLoader 加载。它只信任 $JAVA_HOME/lib/rt.jar(Java 8)或 java.base 等核心模块中的字节码,完全忽略 classpath、自定义 JAR 或本地文件系统里的同名类。
- 你写一个
public class String extends Object { }放进项目,编译能过,但运行时永远不会被加载——请求一发出就被委托到 Bootstrap,它直接返回已加载的官方版本 - 应用类加载器(AppClassLoader)和扩展类加载器(ExtClassLoader)根本不尝试查找或读取你的类文件,它们只是“转发通道”
-
ClassLoader.findSystemClass(String name)是子加载器向 Bootstrap 请求系统类的唯一合法接口,对非系统包返回null,对系统包失败则直接抛异常
绕过委派会被 JVM 主动拒绝
双亲委派不是建议,是 JVM 内置的强制逻辑。一旦你重写 loadClass() 跳过 super.loadClass(),试图让自定义加载器自己加载 java.lang.Thread 这类类,JVM 在 defineClass() 阶段会立即抛出 SecurityException。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 这个校验发生在字节码转为
Class对象之前,由 JVM 原生代码执行,无法绕过 - 报错不是“找不到类”,而是“不允许你定义它”,错误信息明确指向包权限问题
- 即使字节码本身合法,只要加载器不是 Bootstrap 且包名在保护名单内,定义行为直接被拦截
类唯一性由“加载器 + 全限定名”共同决定
Java 规定:两个类是否相同,不仅看名字,还要看是谁加载的。这意味着,哪怕你用非法手段绕过所有限制,成功加载了一个 java.lang.String,它也和 JVM 正常使用的 String 完全不兼容。
-
new String()创建的对象类型是java.lang.String@Bootstrap - 你加载的同名类是
java.lang.String@MyClassLoader,二者属于不同命名空间 - 赋值会报
ClassCastException,调用equals()会失败,静态字段互不共享 - 这种隔离不是靠语法或人工判断,而是类加载器天然形成的命名空间屏障
字节码验证作为最后守门员
即便恶意字节码意外混入(例如通过非法注入),JVM 在链接阶段仍会执行严格验证:
- 检查魔数、主次版本号是否符合规范
- 验证操作数栈与局部变量表类型匹配,防止内存越界或类型混淆
- 确认不能绕过访问控制,比如调用私有方法或修改 final 字段
- 拒绝任何违反 Java 语义的指令序列,如跳转到非法地址、重复初始化等
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










