如何判断对象仍然存活?
1、reference count(引用计数)
查看是否有引用指向该对象,有则说明该对象不是垃圾,反之就是垃圾。
我们通过下图的引用对象案例来说明。
如上图所示,我们可以看到一共是存在四个阶段。
- 第一阶段,有 3 个引用指向该对象,那该对象肯定不是垃圾。
- 第二三阶段,部分引用消失,分别各有 2 个和 3 个引用指向该对象,那该对象仍然不是垃圾。
- 第四阶段,没有任何引用再指向该对象,该对象沦为垃圾。这时垃圾回收器就可以将其回收。
1.2、reference count(引用计数)存在的问题
当出现循环引用时,如下图所示:
我们可以看到,三个对象各自指向循环中的另一个对象,但是没有其他引用指向这三个对象,那这三个对象就属于“一堆垃圾”。
那现在我们上面所说的引用计数就不能解决这个该问题,这时我们就需要使用另外一种定位方式——Root Searching(根可达算法或根搜索算法)。
2、Root Searching(根可达算法或根搜索算法)
所谓的“根”即是:所有的程序都是从 main 方法来运行,在 main 方法里面 new 出来的对象即为根对象。
例如:在 main 方法里面我们 new 了一个 list 集合,在 list 集合中我们又可以存放若干其他对象,那我们就称 list 为根对象,我们顺着根的数据结构往下走,只要存在引用指向的对象,那该对象就不是垃圾,反之不存在引用的对象,那该对象就是垃圾。
如上图所示,对象一、二、三、四、五均是存在根对象的引用,对象五、六之间是我们上面所提到的循环引用,对象八不存在引用,故对象六、七、八是垃圾。
根对象(root)的类型
根对象不仅仅包括我们上面所说的 main 方法里面的对象,属于根对象的还有以下这些:
可以作为GC Roots的主要有四种对象:
- 虚拟机栈(栈帧中的本地变量表)中引用的对象
-
- 比如:各个线程被调用的方法中使用到的参数、局部变量等(局部变量表)。
- 方法区中类静态属性引用的对象
- 方法区中常量引用的对象
-
- 比如:字符串常量池(string Table)里的引用
- 所有被同步锁synchroni zed持有的对象