软件风向标

新闻

栏目

roots攻略 搜寻 锈湖攻略

2023-06-02 19:28:13

垃圾收集(Garbage Collection,下文简称GC)是Java与其它编程语言不同,GC主要考虑三个问题:


哪些内存需要回收?什么时候回收?如何回收?


今天我们主要谈谈JVM如何判断对象可以回收。


常用的算法有两种:


引用计数算法可达性分析算法


引用计数算法


在对象中添加一个引用计数器。每次添加一个引用,计数器将添加1。当引用失效时,计数器将减少1。任何时候,只要计数器为0,就意味着对象可以回收而不引用。


该算法实现简单,判断效率高,但存在一些缺点:

主流的商用JVM没有这样实现。

可达性分析算法


主流商业用途JVM通过可达性分析来判断对象是否可以回收。


该算法的基本思路是:


通过一系列被称为「GC Roots」作为起始节点集,从这些节点开始,通过引用关系向下搜索,搜索路径称为「引用链」,若对象到达GC Roots没有引用链连接,说明对象无法到达,可以回收。


第一次看这段话是不是一脸懵?一开始作者也是,完全不知道是什么意思,后来才慢慢明白。


要理解可达性算法,首先要理解几个问题:


1.什么是对象可达?


对象可达是指双方之间存在直接或间接的引用关系。

根可达或GC Roots可达是指对象到达GC Roots存在直接或间接的引用关系。

如下代码:


public class MyObject {private String objectName;//对象名private MyObject refrence;//依赖对象public MyObject(String objectName) {this.objectName = objectName;}public MyObject(String objectName, MyObject refrence) {this.objectName = objectName;this.refrence = refrence;}public static void main(String[] args) {MyObject a = new MyObject("a");MyObject b = new MyObject("b");MyObject c = new MyObject("c");a.refrence = b;b.refrence = c;new MyObject("d", new MyObject("e")


他们之间的引用关系如图所示:

假设a是GC Roots的话,那么b、c是可达的,d、e不可达。


2、GC Roots是什么?


垃圾回收时,JVM首先要找到一切GC Roots,这个过程叫做 「枚举根节点」 ,这个过程需要暂停用户线程,即触发STW。

然后再从GC Roots向下搜索这些根节点,保留可达对象,回收不可达对象。

那到底是什么呢?GC Roots呢?


GC Roots是对象,是JVM确定目前不能回收的对象(如方法区中类静态属性引用的对象) )。

只有找到这种对象,后面的搜寻过程才有意义,不能被回收的对象所依赖的其他对象肯定也不能回收嘛。


当JVM触发GC首先,所有用户线程都将达到安全点SafePoint时间阻塞,即STW,然后枚举根节点,找到所有GC Roots,然后就可以这样了GC Roots向下搜索,保留可达对象,回收不可达对象。


即使声称几乎不停顿,CMS、G在枚举根节点时,1等收集器也应暂停用户线程。


GC Roots它是一个特殊的对象,也是一个特殊的对象Java在运行过程中,程序必须是根对象。

那么,哪些对象可以成为呢?GC Roots呢?


3.哪些对象可以作为GC Roots?


可以作为GC Roots对象可分为两类:全局对象和执行上下文。

让我们来看看为什么这些对象可以被视为GC Roots。

1.引用方法区静态属性的对象

一种全局对象,Class只要对象本身难以回收,回收条件就非常苛刻Class对象不回收,静态成员不回收。


2.方法区常量池引用的对象

也属于全局对象,如字符串常量池,常量本身初始化后不会改变,所以作为GC Roots也是合理的。


3.方法栈中栈帧本地变量表引用的对象

属于执行上下文中的对象。当线程执行方法时,该方法将法包装成堆栈帧,并将该方法中使用的局部变量存储在堆栈帧的本地变量表中。只要该方法仍在运行中,并且没有离开堆栈,这意味着本地变量表的对象将被访问,GC不应该回收,所以这种对象也可以作为GC Roots。


4、JNI本地方法栈引用的对象

和上一个一样,无非是一个Java方法栈中的变量引用是native方法(C、C )方法栈中的变量引用。


5.被同步锁定的对象

被synchronized锁定对象绝对不能回收,目前有线程持有对象锁,GC如果对象被回收,锁不会失效。


尾巴


综上所述,可达性分析是JVM首先,列出根节点,找到一些必须存活的对象,以确保程序正常运行,然后根据参考关系开始向下搜索,直接或间接参考链存活,没有参考链回收。

相关文章

图文推荐

猜你喜欢

  • 攻略

  • roots

攻略[共148663款]更多>>

roots[共10款]更多>>