启动类加载器(bootstrap classloader)是 java 虚拟机中负责加载核心 api 的顶层加载器,它由 c++ 原生代码实现,专门用于加载 目录下的核心类库。由于它是 jvm 内部的一部分,在 java 代码中无法直接获取其实例,通常通过 getparent() 方法返回 null 来识别其身份。它在双亲委派模型中处于最顶端,优先于其他所有自定义加载器处理核心类的加载请求。

如何验证启动类加载器的存在与范围
要验证启动类加载器的存在及其加载范围,最直接的方法是检查核心类如 java.lang.String 的加载器属性。因为启动类加载器没有对应的 Java 对象,所以调用 getClass().getClassLoader() 会返回 null。我们可以通过编写一个简单的测试程序,遍历 rt.jar 或 modules 中的类并打印其加载器,确认它们确实由启动类加载器处理。这有助于理解为什么用户不能随意替换核心类,以及为什么 System.out.println 等基础操作不依赖任何 Java 层面的加载器。

public class BootstrapLoaderTest {
public static void main(String[] args) {
// 获取 String 类的 Class 对象
Class<string> stringClass = String.class;
// 获取加载该类的 ClassLoader
ClassLoader loader = stringClass.getClassLoader();
// 打印加载器信息
System.out.println("String class loader: " + loader);
// 验证是否为 null,即由 Bootstrap ClassLoader 加载
if (loader == null) {
System.out.println("Loaded by Bootstrap ClassLoader");
} else {
System.out.println("Loaded by: " + loader.getClass().getName());
}
// 进一步验证:尝试获取 rt.jar 中的另一个类
Class<object> objectClass = Object.class;
System.out.println("Object class loader: " + objectClass.getClassLoader());
}
}</object></string>
运行上述代码后,控制台将输出 String class loader: null 和 Loaded by Bootstrap ClassLoader。这证实了 java.lang 包下的类是由启动类加载器加载的。同时,Object 类的加载器也为 null,进一步验证了这一机制。注意,不同 JDK 版本可能将核心库打包为 rt.jar 或模块化系统中的 java.base 模块,但加载行为保持一致。
启动类加载器与其他加载器的关系
启动类加载器与扩展类加载器(Extension ClassLoader)和应用类加载器(Application ClassLoader)共同构成了 Java 的双亲委派模型。启动类加载器负责加载最核心的类,而扩展类加载器负责加载 目录下的类,应用类加载器则负责加载当前类路径(classpath)下的用户类。这种层级结构确保了核心类的唯一性和安全性,防止恶意代码替换核心类。我们可以通过检查 ClassLoader.getSystemClassLoader().getParent()` 来获取扩展类加载器,再调用其 getParent()` 得到 null,从而验证这一层级关系。

public class LoaderHierarchyTest {
public static void main(String[] args) {
// 获取系统类加载器(通常是 Application ClassLoader)
ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
System.out.println("System ClassLoader: " + systemLoader);
// 获取扩展类加载器
ClassLoader extLoader = systemLoader.getParent();
System.out.println("Extension ClassLoader: " + extLoader);
// 获取启动类加载器(应为 null)
ClassLoader bootstrapLoader = extLoader.getParent();
System.out.println("Bootstrap ClassLoader: " + bootstrapLoader);
// 验证 String 类的加载器是否为 null
Class<string> stringClass = String.class;
System.out.println("String loaded by: " + stringClass.getClassLoader());
}
}</string>
运行此代码后,输出将显示系统类加载器、扩展类加载器和启动类加载器(null)。这表明启动类加载器位于层级顶部,且没有父加载器。这种设计确保了核心类的加载优先级最高,且不受用户自定义加载器的影响。如果尝试加载一个不在核心库中的类,例如用户定义的类,它将由应用类加载器加载,并通过双亲委派机制向上委托,直到找到合适的加载器或抛出 NoClassDefFoundError。
启动类加载器加载的具体类有哪些
启动类加载器主要加载 目录下的核心类库,包括 rt.jar 或模块化系统中的 java.base 模块。这些类涵盖了 Java 语言的基础功能,如 java.lang.Object、java.lang.String、java.util.ArrayList 等。我们可以通过列出 rt.jar 中的部分类名来具体说明启动类加载器的加载范围。这些类在 JVM 启动时就被加载,确保应用程序能够使用基本的 Java 功能。此外,启动类加载器还加载一些与 JVM 交互的 native 方法相关的类,如 java.lang.System 和 java.lang.Runtime。
// 示例:列出 rt.jar 中的部分核心类 // java.lang.Object // java.lang.String // java.lang.Integer // java.util.ArrayList // java.io.InputStream // java.net.URL // ...
这些类构成了 Java 应用程序的基础,启动类加载器确保它们在 JVM 启动时即可用。由于启动类加载器由 C++ 实现,其加载逻辑与 Java 层面的加载器不同,但它遵循相同的双亲委派原则。在实际开发中,开发者通常不需要直接与启动类加载器交互,但了解其作用有助于排查类加载相关的问题,如 ClassNotFoundException 或 LinkageError。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











