其他垃圾回收机制
引用计数
特点
- 简单但速度很慢
- 需要单独的字段存储计数器,增加了存储空间的开销。
- 每次赋值都需要更新计数器,增加了时间开销。
- 垃圾对象便于辨识,只要计数器为0,就可作为垃圾回收
- 及时回收垃圾,没有延迟性。
- 不能解决循环引用的问题。
实现
探究模拟对象销毁垃圾回收
通过覆写finalize()方法,查看对象销毁,对象创建可通过构造方法查看
/**
* @author qinlei
* @description 模拟引用计数垃圾回收
* @date 2020/6/17 9:26
*/
public class GarbageCollectedObjects {
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public GarbageCollectedObjects(int age) {
this.age = age;
System.out.println("GarbageCollectedObjects对象--创建了");
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("GarbageCollectedObjects对象--销毁了");
}
}
/**
* @author qinlei
* @description 模拟GC---引用计数
* @date 2020/6/17 9:23
*/
public class ReferenceCounting {
/**
* 模拟查看JAVA垃圾回收
*/
public static void main(String[] args) {
try {
GarbageCollectedObjects garbageCollectedObjects = new GarbageCollectedObjects(5);
garbageCollectedObjects = null;
System.gc();
Thread.sleep(200);
System.exit(0);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
结果:
通过这个示例可了解用JAVA怎么模拟垃圾回收机制(GC).
模拟引用计数
- 首先,每个对象都含有一个引用计数器.当该对象被引用时,计数器加1.
- 当对象的引用离开作用域或者被设置为null时,计数器减1
- 直至计数器减为0时,就会释放对象所占用的内存空间
这里有个问题,当出现循环引用时,会出现:
对象应该被销毁,但是引用不为0的情况
模拟示例
public void test(){
A a = new A();
int ia = 1; //a对象的引用计数
B b = new B();
int ib = 1; //b对象的引用计数
a.setB(b); //a对象引用了b
ib += 1; //即b对象的引用加1
b.setA(a); //b对象引用了a对象
ia += 1; //即a对象的引用加1
a = null;
ia -= 1; //a对象设置为null后 引用减少一个 即减1
b = null;
ib -= 1; //b对象设置为null后 引用减少一个 即减1
System.out.println(ia+"--"+ib);
}
上述代码中,当
设置b为null 也是说b对象该被销毁了 计数应该为0
设置a为null 也是说a对象该被销毁了 计数应该为0
但是实际上,我们打印出来的结果是
这也就是内存泄漏!
所以这就是循环引用出现的对象应该被销毁,但是计数不为0