什么样的对象才能作为 GC ROOT?GC ROOTS 有哪些?

GC 管理的主要区域是 Java 堆,一般情况下只针对堆进行垃圾回收。方法区、栈和本地方法区不被 GC 所管理,因而选择这些区域内的对象作为 GC roots,被 GC roots 引用的对象不被 GC 回收。

所谓 “GC roots”,或者说 tracing GC 的“根集合”,就是一组必须活跃的引用(注意,是一组必须活跃的引用,不是对象)。

详细 GC Root
常说的 GC(Garbage Collector)roots,特指的是垃圾收集器(Garbage Collector)的对象,GC 会收集那些不是 GC roots 且没有被 GC roots 引用的对象。

一个对象可以属于多个 root,GC root 有几下种:

Class:由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。我们需要注意的一点就是,通过用户自定义的类加载器加载的类,除非相应的 java.lang.Class 实例以其它的某种(或多种)方式成为 roots,否则它们并不是 roots。

Thread:活着的线程。

Stack Local:Java 方法的 local 变量或参数。

JNI Local:JNI 方法的 local 变量或参数。

JNI Global:全局 JNI 引用。

Monitor Used:用于同步的监控对象。

Held by JVM:用于 JVM 特殊目的由 GC 保留的对象,但实际上这个与 JVM 的实现是有关的。可能已知的一些类型是:系统类加载器、一些 JVM 知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等。然而,JVM 并没有为这些对象提供其它的信息,因此需要去确定哪些是属于 “JVM持有” 的了。

在 Java 语言里,可作为 GC Roots 对象的包括如下几种:
虚拟机栈(栈桢中的本地变量表)中的引用的对象。
方法区中的类静态属性引用的对象。
方法区中的常量引用的对象。
本地方法栈中JNI的引用的对象。
Tracing GC 的根本思路就是:给定一个集合的引用作为根出发,通过引用关系遍历对象图,能被遍历到的(可到达的)对象就被判定为存活,其余对象(也就是没有被遍历到的)就自然被判定为死亡。

注意再注意:Tracing GC 的本质是通过找出所有活对象来把其余空间认定为“无用”,而不是找出所有死掉的对象并回收它们占用的空间。

GC roots 这组引用是 Tracing GC 的起点。要实现语义正确的 Tracing GC,就必须要能完整枚举出所有的 GC roots,否则就可能会漏扫描应该存活的对象,导致 GC 错误回收了这些被漏扫的活对象。

这就像任何递归定义的关系一样,如果只定义了递推项而不定义初始项的话,关系就无法成立——无从开始;而如果初始项定义漏了内容的话,递推出去也会漏内容。

服务推荐

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值