Java虚拟机 垃圾回收 之 引用计数

本文介绍了引用计数这一古老垃圾回收算法的工作原理与实现思路,包括如何通过计数器判断对象是否可被回收,以及该算法的优点和局限性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自:http://blog.sina.com.cn/s/blog_7880b6e30100ucit.html


引用计数也许是最古老的垃圾回收算法了,但一直不知道具体是怎么实现的,今天闲来无事了,想了一种实现方法,但未经实践,在此先作记录。

 

引言:

    引用计数是唯一一种没有使用根集的垃圾回收算法,该算法使用引用计数器来区分存活对象和不再使用的对象。

 

分析

  1. 一般来说,每个对象对应一个引用计数器。创建对象时,将其计数器置0
  2. 当对象被赋给任意变量时,引用计数器每次加1
  3. 引用变量出了作用域后,该引用变量所引用的对象的计数器减1
  4. 一旦引用计数器为0,对象就满足了垃圾收集的条件。
     

    

具体实现思路如下:

  1. 在对象结构中添加一个域,用来保存本对象被引用的次数,创建对象时置0。
  2. 对象被引用时,计数器加1:
    1. 被实例域引用:putfield_a系列指令,在该指令中为对象的引用计数器加1.
    2. 类的静态域引用:针对java智能卡虚拟机的话,和包一起存亡。
    3. 方法的本地变量应用:astore系列指令,在该指令中为对象的引用计数器减1.
  3. 引用变量出了作用域之后,计数器减1:

    由于方法调用的时候,会为该方法创建一个栈帧,当该方法正常结束,或所抛出的异常在本方法内无法被捕获的话(在本方法内能被正常捕获的话,视为正常结束),都会弹出该栈帧。

    个人理解的出了作用域,就是为该方法创建的栈帧被弹出了。

    故,可以这样实现:弹出栈帧的时候,检查该栈帧内所用引用的对象,并所有所引用的对象的引用计数器分别减一。

  4. 启动垃圾回收的时候,遍历对象表,如果引用计数器为0,则清除该对象,回收其空间;否则,什么也不做。

 

总结

     基于引用计数器的垃圾收集器运行较快,不会长时间中断程序执行,适宜必须实时运行的程序。但引用计数器增加了程序执行的开销,因为每次对象赋给新的变量,计数器加1,而每次引用变量出了作用域后,该引用变量所引用的对象的计数器减1

 

    还有无法解决环形引用的问题,如下:

 

    ClassA(){

    privateB b = null;

    .....

}

 

Class B(){

    privateA a = null;

    .....

}

 

void test(){

    Aa = new A();

    Bb = new B();

 

    a.b= b;

    b.a= a;

}

 

如果没有    最后两行的话,在函数test结束之后,对象ab的引用计数器就为0,处于可以回收状态,但是,有了这两行,将形成环形引用,他们都的引用计数器都为1,无法被回收,如下所示:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值