所有分类
  • 所有分类
  • 未分类

JVM–可作为GC Roots的对象

简介

本文介绍可作为GC Roots的对象有哪些。

对象是否要回收?

判断对象是否要回收有两种方法:引用计数算法、可达性分析算法。JVM是通过可达性分析算法来判断的。

引用计数算法

给对象中添加一个引用计数器。每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器值减1;任何时刻计数器为0的对象就是没有被使用的(需要被回收)。

缺点:无法解决循环引用问题:两个对象互相引用,引用计数始终不为 0,导致无法被回收,而实际上应该需要被回收。

可达性分析算法

在主流的商用程序语言(Java、C#、Lisp)的主流实现中,都是称通过可达性分析(Reachability Analysis)来判定对象是否存活的。

将所有称为“GC Roots”的对象作为起点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain)。当一个对象到GC Roots没有任何引用链相连(用图论的话来说,就是从GC Roots到这个对象不可达)时,则说明此对象是没有被使用的(需要被回收)。如下图所示,对象object5、object6、object7虽然互相有关联,但是它们到GC Roots是不可达的,所以它们将会被判定为是可回收的对象。

可作为GC Roots的对象

Java对象并不是只有用户才能new,虚拟机内部也new了一些。只要从这个顶部对象出发能发现存活对象,它们就是GC Roots。

用户的GC Roots对象

  1. 栈中的对象
    1. 虚拟机栈(栈帧中的本地变量表)中引用的对象。
  2. static修饰的对象
    1. 方法区中类静态属性引用的对象。
  3. static final修饰的对象
    1. 方法区中常量引用的对象。
  4. Native方法引用的对象
    1. 本地方法栈中JNI引用的对象。

GC Roots大全

另见:Help – Eclipse Platform

类型说明
System Class由引导程序/系统类加载器加载的类型。例如,rt.jar中的所有内容(如java.util.*)。
JNI Local本机原生代码中的局部变量,例如用户定义的JNI代码或JVM内部代码。
JNI Global本机原生代码中的全局变量,例如用户定义的JNI代码或JVM内部代码。
Thread Block从当前活动的线程块引用的对象。
Thread已经启动运行的线程 thread。
Busy Monitor忙碌的监视器代码,调用了wait()或notify()或被synchronized同步的。
Java Local局部变量。例如,输入参数或仍在线程堆栈中的方法的局部创建对象。
Native Stack本机原生代码中的输入或输出参数,例如用户定义的JNI代码或JVM内部代码。
Finalizable可终结对象,队列中等待其终结器运行的对象。
Unfinalized未终结对象,具有finalize方法但尚未完成且尚未在终结器队列中的对象。
Unreachable不可达对象,无法从任何其他根访问的对象,MAT使用。
Java Stack FrameJava栈框架,持有局部变量。解析Dump时使用。
Unknown根类型未知对象。MAT分析Dump文件时的特殊类型,归类不可知类型。

0

评论0

请先

显示验证码
没有账号?注册  忘记密码?

社交账号快速登录