JAVA系列: 哪些对象可以成为GC Roots?

 

GC的根本思路

给定一个集合的引用作为根出发,通过引用关系遍历对象图,能被遍历到的(可到达的)对象就被判定为存活,其余对象(也就是没有被遍历到的)就自然被判定为死亡。注意再注意:tracing GC的本质是通过找出所有活对象来把其余空间认定为“无用”,而不是找出所有死掉的对象并回收它们占用的空间。

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

 

 

 

 

判断标准

GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收。

方法区、栈和本地方法栈不被GC所管理,因而选择这些区域内的对象作为GC roots,被GC roots引用的对象不被GC回收。

 

引用计数

堆中的每个对象都有一个引用计数,当对象被引用时引用计数加1,当对象的引用被重新赋值或超出有效区域时引用计数减1,当一个对象被回收后,它所引用的对象的引用计算减1。当一个对象的引用计数变为0时就被回收。

JAVA系列: 哪些对象可以成为GC Roots?

GcObject实例1和实例2的计数引用都不为0,那么如果采用的引用计数算法的话,那么这两个实例所占的内存将得不到释放,这便产生了内存泄露 

JAVA系列: 哪些对象可以成为GC Roots?

根搜索算法(GC Roots )

JAVA系列: 哪些对象可以成为GC Roots?

为了解决引用计数法的循环引用问题,Java使用了可达性分析的方法。

所谓"GCroots,或者说tracingGC的“根集合”就是一组必须活跃的引用

基本思路就是通过一系列”GCRoots”的对象作为起始点,从这个被称为GC Roots的对象开始向下搜索,如果一个对象到GCRoots没有任何引用链相连时,则说明此对象不可用。也即给定一个集合的引用作为根出发,通过引用关系遍历对象图,能被遍历到的(可到达的)对象就被判定为存活,没有被遍历到的就自然被判定为死亡。

JAVA系列: 哪些对象可以成为GC Roots?

GC Roots缺点:需要分析大量数据,消耗大量时间、分析过程需要GC停顿(引用关系不能发生变化),即停顿所有Java执行线程(称为"Stop The World",是垃圾回收重点关注的问题)STW。

 

GC Roots对象

在Java语言里,可作为GC Roots对象的包括如下几种: 

  • 虚拟机栈(栈帧的局部变量表)所引用的对象;
  • 本地方法栈的JNI所引用的对象;
  • 方法区的静态变量、常量所引用的对象;