一、什么是 ClassLoader?
ClassLoader(类加载器) 是 Java 虚拟机(JVM)用来加载 .class 文件(字节码)的对象。它负责把类的字节码文件读进内存,并转换成 JVM 可以识别的 Class 对象。
简单来说,你写的 Java 代码会被编译成 .class 文件,运行时由 ClassLoader 加载进 JVM,才能被执行。
分析一下 ClassLoader 的作用:
- 加载类:把磁盘上的
.class文件或 jar 包里的类加载到内存。 - 隔离类:不同 ClassLoader 加载的类,哪怕名字一样,也可能是不同的类型(类隔离,常用于插件机制)。
- 资源查找:不仅加载类,还可加载配置文件、图片等资源。
- 扩展性:你可以自定义 ClassLoader,实现特殊的类加载逻辑(如加密、网络加载等)。
二、ClassLoader 的分类(JVM 默认有三种)
-
Bootstrap ClassLoader(引导类加载器)
- 加载 Java 核心类库(rt.jar),比如
java.lang.*、java.util.* - 不是 Java 实现的,没有对应的 Java 对象,通常在代码里表现为
null
- 加载 Java 核心类库(rt.jar),比如
-
Extension ClassLoader(扩展类加载器)
- 加载
$JAVA_HOME/lib/ext目录下的 jar 包 - 对应类是
sun.misc.Launcher$ExtClassLoader
- 加载
-
Application ClassLoader(系统类加载器)
- 加载应用 classpath 下的类和 jar
- 对应类是
sun.misc.Launcher$AppClassLoader
你也可以自己写 ClassLoader,做一些特殊用途。
三、双亲委派机制是什么?为什么需要?
这是 Java 类加载器设计的一个重要机制。双亲委派机制的核心思想是:一个 ClassLoader 在加载类时,首先把请求交给父级 ClassLoader,只有父级无法加载时,自己才尝试加载。
步骤解析:
- 收到加载请求:比如你要加载
java.lang.String。 - 请求父 ClassLoader:当前 ClassLoader 先让父 ClassLoader 去加载。
- 递归委托:一直委托到 Bootstrap ClassLoader。
- 父级加载成功:如果父级能加载,直接返回该类。
- 父级加载失败:如果父级没找到,才由当前 ClassLoader 自己加载。
代码伪流程:
Class findClass(String name) {
// 1. 委托父加载器
Class c = parent.loadClass(name);
if (c != null) {
return c;
}
// 2. 父加载器没找到,自己加载
return this.findClass(name);
}
为什么要这样设计?
- 安全性:保证 Java 核心类不会被篡改——比如你不能自己写个
java.lang.String并让 JVM 用你的类。 - 避免重复加载:一个类只会被一个 ClassLoader 加载一次,避免冲突。
- 层级清晰:不同类加载器只负责自己范围内的类,结构清晰。
四、举个例子
假设你写了一个 com.example.MyClass,JVM 想加载它:
- Application ClassLoader 收到请求,先问父级 Extension ClassLoader。
- Extension ClassLoader 再问 Bootstrap ClassLoader。
- Bootstrap ClassLoader找不到,返回。
- Extension ClassLoader也找不到,返回。
- Application ClassLoader最终自己加载 classpath 里的
com.example.MyClass。
而如果你试图加载 java.lang.String,Application ClassLoader会发现父级 Bootstrap ClassLoader已经加载了,直接返回,不会再自己加载。
五、实际应用场景
- 插件开发:自定义 ClassLoader,实现插件隔离。
- 热部署:用自定义 ClassLoader加载新版本类,实现热替换。
- 安全沙箱:通过类加载器控制哪些类能被加载。
总结
- ClassLoader 是 JVM 加载类和资源的工具,决定了类的来源和隔离性。
- 双亲委派机制 保证了安全和一致性,防止类被重复加载或被恶意篡改。

1万+

被折叠的 条评论
为什么被折叠?



