java GC垃圾回收

垃圾回收机制html

1、引用计数java

特色:jvm

简单,速度慢orm

原理:htm

每一个对象都含有一个引用计数器,当有引用链接值对象是,引用计数加1.当引用离开做用域或被置为null时,引用计数减1.虽然管理引用计数的开销不大,但这项开销在整个程序生命周期中将持续发生。垃圾回收器会在含有所有对象的遍历表上遍历,当发现某个对象的引用计数为0时,就释放其占用的空间。可是,引用计数模式常常会在计数值变为0时当即释放对象。这种方法还有个缺陷,若是对象之间存在循环引用,可能会出现对象应该被回收,但引用计数却不为0的状况。对垃圾回收器而言,定位这样的的交互自引用的对象组所需的工做量极大。对象

评价:blog

这种方式经常使用来讲明垃圾收集的工做方式,但彷佛从未被应用于java虚拟机实现中。生命周期

2、遍历全部的引用进程

思想:内存

对任何活的对象,必定能最终追溯到器存活在堆栈或静态存储区之中的引用。这个引用链条可能会产国数个对象层次,由此,若是从堆栈和静态存储区开始,遍历全部的的引用,就能找到全部活的对象。这种方式解决了交互自引用的对象组的问题。

这种方式下java虚拟机将此采用一种自适应的垃圾回收技术。至于如何处理找到的存活对象,取决于不一样的实现。

  1. 中止-复制

    先暂停程序的运行(因此它不属于后台回收模式),而后将全部存活的对象从当前堆复制到另外一个堆,没有被复制的所有都是垃圾。当对象被复制到新堆时,它们是一个挨着一个的,因此新堆保持紧凑排列,而后就能够按前述方法简单直接的分配新空间了。

    评价:

    这种所谓的复制式回收器,效率会下降,两个缘由。

    首先,得有两个堆,而后在两个分离的堆之间来回倒腾,从而得维护比实际须要多一倍的空间。某些java虚拟机对此问题的处理方式是,按需从堆中分配几块较大的内存,复制动做发生在这些大块内存之间。

    第二个问题在于复制,程序进入稳定状态以后,可能只会产生少许垃圾,甚至没有垃圾。尽管如此,复制式回收器仍然会将全部内存自一处复制到另外一处,这很浪费。为了不这种情形,一些java虚拟机会进行检查:要是没有新垃圾产生,就会转换到另外一种工做模式(即:自适应)。这种模式成为标记-清扫,sun公司早期的java虚拟机使用了这种技术。对通常用途而言,标记-清扫方式速度至关慢,可是当你知道只会产生少许垃圾甚至不会产生垃圾时,它的速度就很快了。

  2. 标记-清扫

    思路一样是从堆栈和静态存储区出发,遍历全部的引用,进而找出全部存活的对象。每当它找到一个存活的对象,它就会给对象设一个标记,这个过程当中不会回收任何对象。只有所有标记工做完成的时候,清理动做才会开始。在清理过程当中,没有标记的对象将被释放,不会发生任何复制动做。因此剩下的空间是不连续的,垃圾回收器要是但愿获得连续空间的话,就得从新整理剩下的对象。

    3、综述

    “中止-复制”的意思是这种垃圾回收动做不是在后台进行的;相反,垃圾回收动做发生的同时,程序将会被暂停。在sun公司的文档中会发现,许多参考文献将垃圾回收视为低优先级的后台进程,但事实上垃圾回收器在sun公司早期版本的java虚拟机中并不是以这种方式实现的。当可用内存数量较低时,sun版本的垃圾回收器会暂停运行程序,一样,“标记-清扫”工做也必须在程序暂停的状况下才能进行。

    如前文所述,在这里所讨论的java虚拟机中,内存分配以较大的“块”为单位。若是对象较大,它会占用单独的块。严格来讲,“中止-复制”要求在释放旧有对象以前,必须先把全部存活对象从旧堆复制到新堆,这将致使大量内存复制行为。有了块以后,垃圾回收器在回收的时候就能够往废弃的块里拷贝对象了。每一个块都用相应的“代数”来记录他是否还存活。一般,若是块在某处被引用,其“代数”会增长;垃圾回收器将对上次回收动做以后新分配的块进行整理。这对处理大量短命的临时对象颇有帮助。垃圾回收器会按期进行完整的清理动做——大型对象仍然不会被复制(只是其代数会增长),内含小型对象的块则被复制并整理。java虚拟机会进行监视,若是全部对象都很稳定,垃圾回收器的效率下降的话,就切换到“标记-清扫”方式;一样java虚拟机会跟踪“标记-清扫”的效果,要是对空间出现不少碎片,就会切换回“中止-复制”方式。这就是“自适应”技术。(自适应的、分代的、中止-复制、标记-清扫式垃圾回收器)

    4、其余文章

    看了一篇讲解详细的文章,与上面写的机制可以对应起来,能够看一下,可以清楚经常使用的jvm的详细的各类垃圾回收方式。http://www.cnblogs.com/zhguang/p/3257367.html#commentform

相关文章
相关标签/搜索