注塑厂选 ERP,这 5 个功能是刚需--别的行业用不上,但你不能没有
2026/9/30 11:30:07
Java 类加载机制是 JVM(Java 虚拟机)的核心组成部分,负责将编译后的.class文件(字节码)从磁盘、网络或其他来源加载到内存中,并转换为可执行的 Java 类对象。整个过程遵循双亲委派模型,确保安全性和一致性。
一个类从加载到卸载,主要经历以下 5 个阶段:
加载(Loading)
java.lang.Class对象(在堆中)。连接(Linking)
初始化(Initialization)
<clinit>方法(编译器自动生成)。使用(Using)
卸载(Unloading)
Java 默认使用三层类加载器(Bootstrap + Extension + Application),构成层次结构:
| 类加载器名称 | 加载路径 | 特点 |
|---|---|---|
| Bootstrap ClassLoader(启动类加载器) | $JAVA_HOME/lib中的核心类库(如 rt.jar:Object、String、System 等) | 用 C++ 实现,无 Java 对象引用(null) |
| Extension ClassLoader(扩展类加载器) | $JAVA_HOME/lib/ext目录下的 jar | 父是 Bootstrap |
| Application ClassLoader(应用类加载器,也称 System ClassLoader) | classpath 指定的路径(项目中的 classes、依赖 jar) | 父是 Extension,通常加载我们写的代码 |
此外还有:
ClassLoader,重写findClass()方法。这是 Java 类加载机制的核心设计,工作流程:
优点:
打破双亲委派的情况:
loadClass()方法(不推荐)。以下操作会触发类初始化(执行<clinit>):
new创建对象Class.forName("com.test.MyClass")(默认初始化,可传 false 跳过)java.lang.invoke.MethodHandle的 REF_getStatic 等不会触发初始化的情况:
Class.forName("xxx", false, loader)classParent{static{System.out.println("Parent static block");}publicstaticintvalue=100;}classChildextendsParent{static{System.out.println("Child static block");}}publicclassTest{publicstaticvoidmain(String[]args){System.out.println(Child.value);// 输出:Parent static block → 100// Child static block 不会执行,因为 Child 类未被主动使用}}一个类会被加载几次?
正常情况下只加载一次(由某个类加载器加载)。
如何打破双亲委派?
自定义类加载器,重写loadClass(),或使用线程上下文类加载器。
Tomcat 如何实现 Web 应用隔离?
每个 Web 应用使用独立的 WebappClassLoader,优先加载本应用的类,打破双亲委派。
为什么 String 类不能被自定义覆盖?
因为它由 Bootstrap ClassLoader 加载,用户自定义的 String 在不同命名空间。
Java 类加载机制的核心是:
理解类加载机制对深入掌握 JVM、Spring 容器、热部署、插件化开发至关重要。