哪些可以作为GC Roots

主要的GC算法


  • 引用计数
    不赘述了,主要是无法解决互相引用的问题
  • 可达性分析
    就是从一些叫做GC Roots的引用开始,一步一步的找能达到的对象,如果没达到,那么就不可达的,就会开始回收它。

HotSpot采用的是可达性分析。
那么哪些可以作为GC Roots呢?

书上的


在《深入理解Java虚拟机-JVM高级特性与最佳实践》中,简单的提了一下

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(native方法)引用的对象

简单解释下

第一种就是指当前的Java线程中正在调用的方法的引用类型的参数,局部变量,临时值,这个具有随机性。

第二种就是指类对象的引用对象,比如

1
2
3
public class Solution {
private static List<String> list = new LinkedList<>();
}

这里的list就是这种。

第三种是指的常量一般指static final这种,比如

1
2
3
public class Solution {
public static final String name = "hello";
}

这里的name就是,当然枚举类中的也是。

第四种就是native方法了,就是一般是c语言或者c++写的。

再进行拓展


我又去搜了一下。

又找到了更具体的一下,其实哪些能作为GC Roots在一定程度上也是依赖收集器的设计的。

来自RednaxelaFX的答案

  • (看情况)所有当前被加载的Java类
  • (看情况)Java类的引用类型静态变量
  • (看情况)Java类的运行时常量池里的引用类型常量(String或Class类型)

这里还多了Class类型,。。。。

eclipse的文档网站,找到了更为详细的

eclipse

  • System Class
    被bootstrap类加载器加载的类

  • JNI Local
    JNI定义的局部变量

  • JNI Global
    JNI定义的全局变量

  • Thread Block
    当前线程块中的对象

  • Thread
    未停止的线程

  • Busy Monitor
    调用了wait()或者notify()或者正在进行同步的对象和类

  • Java Local
    当前线程虚拟机栈中的本地变量

  • Native Stack
    本地方法栈中的对象

  • Finalizable
    一个正在在等待finalize的对象

  • Unfinalized
    拥有finalize方法,但是不在等待finalize的对象

  • Unreachable
    一个不可达的对象,但是仍然被Memory Analyzer标记为GC Root的对象
    这个的解释就是对于一些小对象,GC觉得收集它太浪费珍贵的GC时间了,就放弃了。

  • Java Stack Frame
    Java栈帧,如果你设定栈帧也为一个对象的话

  • Unknown
    其他未知的

总结


上面说的很多重复的,有些是看不懂的。所以我自己总结了下

  • 所有线程当前虚拟机栈(栈帧中的本地变量表)中引用的对象,包括局部变量,参数对象。
  • 方法区中类静态属性引用的对象
  • 方法区中常量引用的对象
  • 本地方法栈中JNI(native方法)引用的对象,包括局部变量和全局变量
  • 被bootstrap类加载器加载的类
  • 当前所有活跃的线程
  • 调用了wait()或者notify()或者正在进行同步的对象和类
  • 一个正在在等待finalize的对象
  • 拥有finalize方法,但是不在等待finalize的对象
  • 一个不可达的对象,但是仍然被Memory Analyzer标记为GC Root的对象