类加载器与类垃圾回收之间是否存在循环依赖?
类加载器与类的GC循环依赖问题解答
一、双向引用确实存在,但不阻碍GC回收
你提到的循环引用是真实存在的:
- 每个
Class对象通过getClassLoader()方法可获取加载它的类加载器实例,说明Class内部持有类加载器的引用; - 类加载器实例(比如
URLClassLoader)会维护已加载类的集合(通常是哈希表类结构),避免重复加载,因此类加载器也持有它所加载类的引用。
但这种双向循环引用不会成为GC回收的障碍,因为JVM垃圾回收采用可达性分析算法,而非早期的引用计数法——只要类加载器+类的组合整体不再被GC Roots(系统类加载器、活跃线程、静态变量等)可达,就会被标记为可回收。
二、类加载器与类可被GC回收的条件
满足以下所有条件时,类加载器及其加载的类会被GC回收,无需等待JVM关闭:
- 类加载器实例本身不再被任何GC Roots引用(比如Web容器卸载应用时,会切断对该应用专属类加载器的所有引用);
- 该类加载器加载的所有类的所有实例都已被完全回收;
- 这些类的
Class对象本身不再被任何GC Roots引用(比如没有其他活跃类引用它们,也没有反射API留存的引用)。
三、实际场景示例
最典型的例子是Web容器热部署:比如Tomcat卸载旧Web应用时,会清理对WebAppClassLoader的所有引用,此时这个类加载器以及它加载的所有符合条件的类,会在后续GC周期中被回收,无需重启JVM。
四、需要注意的回收阻碍点
如果存在以下情况,可能会阻止类加载器和类的回收:
- 类的静态变量持有外部强引用(比如静态变量指向活跃对象);
ThreadLocal中留存了该类的实例或Class对象,且对应线程仍在运行;- 反射API获取的类对象被其他活跃代码持有引用。
内容的提问来源于stack exchange,提问作者pjj
相关产品推荐
相关产品推荐

