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

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

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

其内存图示如下

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

内存图示

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


分享到:


相關文章: