判断对象是否凉了的两个算法

判断一个对象是否为垃圾的算法主要有如下这两种:

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

下面我们来分别看一下。

引用计数算法

为对象添加一个引用计数器,当对象增加一个引用时计数器加 1,引用失效时计数器减 1。引用计数为 0 的对象可被回收。

优点:

  • 实现简单
  • 执行效率高,对程序的执行影响较小

引用计数算法在大部分情况下它都是一个不错的算法,也有一些比较著名的应用案例,比如使用 ActionScript3 的 FlashPlayer、Python 语言都使用了引用计数算法来进行内存管理。

但是引用计数算法的缺点也非常的明显,它很难解决对象之间相互循环引用的问题,所以主流的 Java 虚拟机里面没有选用引用计数算法来管理内存

循环引用的例子:

public class ReferenceCounterProblem{

    public ReferenceCounterProblem instance = null;

    public static void main(String[] args) {
        ReferenceCounterProblem a = new ReferenceCounterProblem();
        ReferenceCounterProblem b = new ReferenceCounterProblem();
        a.instance = b;
        b.instance = a;
        a = null;
        b = null;
    }
}

这种情况下,原来 a 和 b 所指向的对象都无法再访问了(因为 a 和 b 均置为 null 了),但是,使用引用计数算法的话,a 和 b 所指向的对象,此时的引用计数器均为1,且不会再改变了,所以这两个对象不会被回收,此时内存泄露发生。

可达性分析算法

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

这个算法的基本思想就是 通过一系列的称为 ”GC Roots“ 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可被回收的。 相反,可达的对象都是存活的。

如下图
在这里插入图片描述
Object 1 ~ 4 均判定为存活的对象,而 Object 5 ~ 7 均判定为可回收的。

可以作为 GC Roots 的对象主要有如下四种:

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

猜你喜欢

转载自blog.csdn.net/u013568373/article/details/94171039