JVM-GC垃圾回收算法-引用计数法

本文介绍了JVM中的引用计数算法,这是一种用于垃圾回收的机制。该算法在每个对象上维护引用计数,当计数为0时对象可回收。然而,由于无法处理循环引用和执行时的性能开销,Java并未采用此算法。文章还通过代码示例解释了循环引用导致的问题,指出这种情况下可能出现内存泄漏。

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存在的问题

该算法存在两个问题:

(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);
}

其内存图示如下

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


大家可以关注本人公众号【Mr羽墨青衫】,会定期推送一些原创技术文章。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值