类卸载需满足三条件:ClassLoader被回收、其加载的所有类无任何引用、该ClassLoader未被JVM内部保留;卸载发生在Full GC或元空间GC时,伴随ClassLoader对象回收而批量清理其元数据。

Java 类的卸载不是由程序员直接触发的,而是 JVM 在满足特定条件时,配合垃圾回收(GC)机制自动完成的。类卸载本质上是卸载 java.lang.Class 对象及其关联的 ClassLoader、常量池、方法区(元空间)中对应的数据结构。它只发生在**整个类加载器被回收的前提下**,且该加载器加载的所有类都不再被任何地方引用。
类卸载的前提:类加载器必须可被回收
一个类能否被卸载,根本取决于它所属的 ClassLoader 实例是否变成垃圾对象。JVM 不会单独卸载某个类,而是以类加载器为单位批量清理其加载的所有类。因此,只有当以下条件全部满足时,类才可能被卸载:
- 该类加载器本身已无任何强引用(包括线程上下文类加载器、静态字段、本地变量等)
- 该类加载器加载的所有
Class对象都不可达(即没有活跃实例、静态成员、引用链指向它们) - 该类加载器没有被 JVM 内部保留(如启动类加载器、平台类加载器永远不会被回收)
垃圾回收如何参与类卸载
类卸载实际发生在Full GC 或元空间 GC 触发后,且类加载器判定为可回收对象时。具体流程如下:
- JVM 在 GC 过程中识别出某自定义类加载器(如
URLClassLoader)已无任何强引用,且其所有加载的类对象也不可达 - 在回收该类加载器对象的同时,JVM 清理其关联的元空间(Metaspace)中对应的类元数据(Klass 结构、常量池、JIT 编译代码等)
- 这个过程不是每次 GC 都发生,通常需要显式触发或等待元空间压力增大(如频繁创建和丢弃类加载器)
注意:HotSpot 中,元空间的垃圾回收默认与老年代 GC 耦合(可通过 -XX:+ClassUnloadingWithConcurrentMark 优化),但类卸载本身仍依赖类加载器对象被回收这一前提。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
常见可触发类卸载的场景
以下情况较容易观察到类卸载行为(需配合 JVM 参数如 -XX:+TraceClassUnloading 验证):
- 使用
URLClassLoader动态加载 JAR 并显式置 null、不再持有引用,之后触发 Full GC - Web 容器(如 Tomcat)中应用热部署:旧应用的
WebAppClassLoader被丢弃,新实例替代,旧加载器及所加载类在后续 GC 中被清理 - OSGi 框架中 Bundle 卸载,其专属类加载器被回收,连带卸载所有导出/导入的类
而 System ClassLoader 或自定义类加载器被静态字段长期持有,则类永远无法卸载——这是内存泄漏的常见原因。
如何验证类是否被卸载
可通过 JVM 启动参数辅助观察:
-
-XX:+TraceClassUnloading:打印每次类卸载的日志(如[Unloading class com.example.MyClass 0x00000008002a1000]) -
-XX:+PrintGCDetails -XX:+PrintGCTimeStamps:结合 GC 日志,确认卸载是否发生在某次 Full GC 后 - JDK 工具如
jstat -gc <pid>查看 Metaspace 使用量是否回落,间接反映卸载效果
注意:即使满足条件,JVM 也可能因 GC 策略未执行而延迟卸载;类卸载不是即时强保证行为,而是“可卸载”而非“必卸载”。

















