类的GC根是什么?

48
在Java中,有一些特殊的对象被称为垃圾收集根 (GC roots)。它们作为垃圾收集标记机制的根对象(见图片)。
这篇文章介绍了四种类型的GC根:本地变量、活动线程、静态变量和JNI引用
同时也提到:

类本身可以被垃圾回收。

GC根不会被回收,因此类本身不是GC根。
那么,对于类来说,GC根是什么呢?

1
GC根是您为所有内容列出的那些。您的问题实际上是关于通常持有对类对象引用的对象类型是什么。 - biziclop
2个回答

33

那么类的GC roots是什么?

实际上是类加载器 - 通过其他GC roots。

如果没有任何东西可以访问类加载器 - 这意味着没有任何东西可以访问由该类加载器创建的任何类或这些类的任何实例 - 那么该类加载器和它创建的类都有资格进行垃圾回收。保持它们存活直到那时是必要的,以便Class::forName和ClassLoader::findClass即使在类的静态初始化程序不可达时也可以是幂等的。

隐藏类(参见https://openjdk.java.net/jeps/371)是此规则的例外。作为OpenJDK的一个实现细节,方法引用、lambda和使用java.lang.reflect.Proxy的静态方法创建的代理的类也是如此。类加载器不会对这些类持有强引用。


类加载器实例存储在堆中吗? - gstackoverflow
1
@gstackoverflow:它们肯定不在堆栈上。具体在堆的哪个部分是另一回事。 - Jon Skeet
@gstackoverflow:那是堆的一部分。我所说的“堆的哪个精确部分”是另一回事。 - Jon Skeet
2
正式的Oracle文档将PermGen称为堆的一部分,但通常在社区中,堆= [年轻代] + [老年代]。 - gstackoverflow

21

垃圾回收根是指可以从堆以外访问的对象。

内存分析器按照以下列表将垃圾回收根进行分类:

  1. 由系统ClassLoader加载的类
    • JDK类(如java.*)中的静态字段
  2. 活动线程
    • 堆栈 - 局部变量、方法参数
    • java.lang.Thread实例
  3. 作为同步监视器持有的对象
  4. JNI引用
  5. JVM特殊...

来源1 来源2


2
在YourKit文档中也有很好的参考资料:https://www.yourkit.com/docs/java/help/gc_roots.jsp - Juraj Martinka
关于“作为同步监视器持有的对象”的问题。 持有同步化对象的线程会一直存在于某个活跃线程的堆栈上吗? - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接