Mr羽墨青衫

欢迎食用,今天的配菜特别丰盛!

分享原创技术文章,源于生活、工作、coding的结晶~
  menu
36 文章
6 评论
171357 浏览
1 当前访客
ღゝ◡╹)ノ❤️

Java垃圾回收算法-引用计数法

🌹🌹如果您觉得我的文章对您有帮助的话,记得在GitHub上star一波哈🌹🌹

🌹🌹GitHub_awesome-it-blog 🌹🌹


GC的出现解放了程序员需要手动回收内存的苦恼,但我们也是要了解GC的,知己知彼,百战不殆嘛。
常见的GC回收算法主要包括引用计数算法、标记清除算法、复制算法、标记压缩算法、分代算法以及分区算法。
今天来聊聊引用计数算法。

1 原理

顾名思义,此种算法会在每一个对象上记录这个对象被引用的次数,只要有任何一个对象引用了次对象,这个对象的计数器就+1,取消对这个对象的引用时,计数器就-1。任何一个时刻,如果该对象的计数器为0,那么这个对象就是可以回收的。

打个比方:

public static void method() {
    A a = new A();
}

public static void main(String[] args) {
    method();
}

main函数调用method方法,method方法中new了一个A的对象,赋值给局部变量a,此时堆内存中的对象A的实例的计数器就会+1。当方法结束时,局部变量会随之销毁,堆内存中的对象的计数器就会-1。

2 存在的问题

该算法存在两个问题:

  • 无法处理循环引用的情况。
  • 从上述的原理可知,堆内对象的每一次引用赋值和每一次引用清除,都伴随着加减法的操作,会带来一定的性能开销。

所以Java没有使用这种算法来实现GC。

下面来解释一下第一个问题,循环引用的情况。

即对象A引用对象B,对象B引用对象A。

考虑如下代码:

class A {
    private B b;
    public void setB(B b) {
        this.b = b;
    }
}

class B {
    private A a = new A();
    public void setA(A a) {
        this.a = a;
    }
}

public void method() {
    A a = new A();
    B b = new B();
    a.setB(b);
    b.setA(a);
}

其内存图示如下

GC引用计数法循环引用图示.jpg

method方法中,执行完两个set后,method方法结束,图中两条红线引用消失,可以看到,留下两个对象在堆内存中循环引用,但此时已经没有地方在用他们了,造成内存泄漏。两个对象就凌乱在风中不知所措了。


标题:Java垃圾回收算法-引用计数法
作者:Lord-X
地址:http://blog.feathers.top/articles/2019/08/03/1564808256689.html

评论