java垃圾回收器工作机制

引用计数

​ 引用计数是简单但速度很慢的垃圾回收技术。每个对象都含有一个引用计数器,当有引用连接对象时,引用计数加1。当引用离开作用域或被置为null时,引用计数减1。虽然管理引用计数的开销不大,但这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象的引用计数为零时,就释放其占用的空间(但是,引用计数模式会在计数值变为零时,立即释放对象)。这种方法有个缺陷,如果对象之间存在循环应用,可能会出现“对象应该被回收,但引用计数却不为零”的情况。对垃圾回收器来说,定位这样的交互引用的对象组所需的工作量极大。引用计数常用来说明垃圾收集的工作方式,但视乎未被应用于任何一种java虚拟机的实现中。
​ 在一些跟快的模式中,垃圾回收器并非基于引用计数技术。它们依据的思想是:对任何“活”的对象,一定能最终追溯到其存活在堆栈或静态存储区中的引用。这个引用链条可能会穿过数个对象层次。由此,如果从堆栈和静态存储区开始,遍历所有的引用,就能找到所有“活”的对象。对于发现的每个引用,必须追踪它所引用的对象,然后是此对象包含的所有的引用,如此反复进行,直到“根源于堆栈和静态存储区的引用”所形成的网络全部被访问为止。你所访问过的对象必须都是“活”的。注意,这就解决了“交互自引用的对象组”的问题—这种现象根本就不会被发现,因此也就被自动回收了。

自适应的垃圾回收技术

​ 在这种方式下,java虚拟机将采用一种自适应的垃圾回收技术。至于如何处理找到的存活对象,取决于不同的java虚拟机的实现。有一种做法名为停止-复制(stop-and-copy)。显然,这意味着,先暂停程序的运行(所有他不属于后台回收模式),然后将所有的存活对象从当前堆复制到另一个堆,没有被复制的全部都是垃圾。当对象被复制到新堆时,他们是一个挨着一个的,所有新堆保持紧凑排列,然后就可以按着前述方法,直接的分配新空间了。
​ 当把对象从一处搬到另一处时,所有指向它的那些引用都必须修正。位于堆或静态存储区的引用可以直接被修正,但可能还有其它指向这些对象的引用,它们在遍历的过程中才能被找到(可以想象有个表格,将就地址映射至新地址)。
​ 对于这种所谓的“复制式回收器”而言,效率会降低,这有两个原因。首先,得有两个堆,然后得在这两个分离的堆之间来回倒腾,从而得维护比实际多一倍的空间。某些java虚拟机对此处理得方式是,按需从内存中分配几块较大得内存,复制动作发生在这些大块内存之间。
​ 第二个问题在于复制。程序进入稳定状态之后,可能只会产生少量垃圾,甚至没有垃圾。尽管如此,复制式回收器仍然会将所有内存自一处复制到另一处,这很浪费。为了避免这种情况,一些java虚拟机进行检查:要是没有新垃圾产生,就会转换成另一种工作模式(即“自适应”)。这种模式称为标记-清扫,速度相当慢,但是当你知道只会产生少量垃圾甚至不产生垃圾时,它得速度就很快了。
标记-清扫所依据得思路同样是从堆栈和静态存储区出发,遍历所有的引用,进而找出所有存活的对象。每当它找到一个对象,就会给对象一个标记,这个过程不会回收任何对象。只有全部标记工作完成的时候,清理动作才会开始。在清理的过程中,没有标记的对象将被释放,不会发生任何复制动作,所有剩下的堆空间是不连续的,垃圾回收器要是希望得到连续空间的话,就得重新整理剩下的对象。
停止-复制的意思是这种垃圾回收动作不是在后台进行的;相反,垃圾回收动作发生的同时,程序将会被暂停。在Sun公司的文档发现,许多参考文献将垃圾回收视为低优先级的后台进程。当可用内存数量较低时,Sun版本的垃圾回收器会暂停运行程序,同样,标记-清扫工作也必须在程序暂停的情况下才能进行。
​ 如前文所述,在这里所讨论的java虚拟机中,内存分配以较大的块为单位。如果对象较大,它会占有单独的块。严格来说,停止-复制要求释放所有旧对象之前,必须把所有存活的对象从就对复制到新堆,这将导致大量的内存复制行为。有了块以后,垃圾回收器在回收的时候就可以往废弃的块里拷贝对象了。每个块都用相应的代数来记录它是否还存活。通常,如果快在某处被引用,其代数会增加;垃圾回收器将对上次回收动作之后新分配的块进行整理。这对处理大量短命的临时对象很有帮助。垃圾回收器会定期进行完整的清理动作—大型对象仍然不会被复制(只是其代数会增加),内含小型对象的那些快则被复制并整理。java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到标记-清扫模式;同样,java虚拟机会跟踪标记-清扫的效果,要是堆空间出现很多碎片,就会切换回停止-复制模式。这就是“自适应”技术,你可以给他一个啰嗦的名字“自适应的、分代的、停止-复制、标记-清扫”式垃圾回收器。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值