java的垃圾收集算法和垃圾收集器

[来源] 达内    [编辑] 达内   [时间]2012-11-08

在jdk1.6 update14中提供了一个使用版本,与前面的cms相比,他是基于“标记-整理”算法,不会产生内存碎片,另外他可以精确的控制停顿,让垃圾回收不超过N毫秒,另外他还可以在不牺牲吞吐量的情况下完成低停顿的垃圾回收

  1.垃圾回收算法

  1.1标记-清除

  该算法主要分为标记和清除两个阶段,先对需要回收的对象进行标记,然后再进行清除,该算法的有点是简单,缺点有两个,一个是效率问题,标记和清除的效率都不高,另一个问题是空间问题,标记清除之后会造成大量的空间碎片,当程序需要分配一个大对象而无法找到连续的空间时就必须出发一次垃圾回收。

  1.2复制算法

  该算法是将内存空间分为大小相等的两块,在其中的一块进行对象的分配,需要垃圾回收时将其中一块存活的对象拷贝到另一块即可,然后把用过的内存块给清理掉,该算法的有点是:不用考虑内存碎片问题,实现简单,运行高效,缺点是:将内存缩小为了原来的一半,代价有点儿高。

  现代的虚拟机都是采用此中算法来进行新生代的垃圾回收的,由于java中的新生代对象具有”朝生夕死“的特点,所以讲内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和Survivor空间,HopSpot默认的比例是8:1,按照此种比例,新生代的空间为90%,只有10%的空间会被浪费掉,如果进行了一次垃圾回收survivor仍然不能满足空间的需要,此时需要通过分配担保机制将相关的对象分配到老年代中。

  1.3标记-整理算法

  复制算法在对象存活率较高的情况下就要执行较多的复制操作,效率会变低,另外如果不想浪费50%的空间,还需要进行分配担保机制,以应对100%极端存活的情况,所以老年代不用此种算法。老年代采用”标记-整理“的算法,标记过程和标记-清除算法一样,但是整理却是所有存活的对象向一端移动,然后清理掉边界意外的内存。

  1.4分代收集算法

  当前的商业虚拟机都此种收集算法,根据对象的存活周期将内存分为几块,一般讲java堆分为新生代和老年代,在新生代,采用复制算法,而对于老年代,对象存活率高,没有额外的空间进行分配担保,就不许使用”标记-整理“ 或者”标记-清除“进行垃圾回收。

  2.垃圾收集器

  2.1Serial 收集器

  特点:是一个单线程的垃圾回收期,在进行垃圾回收时必须暂停其他所有的工作线程。

  优点:简单而高效,没有线程交互的开销。Serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择,也是该模式下的默认垃圾收集器。

  2.2ParNew收集器

  是Serial收集器的多线程版本,属性和参数与Serial收集器相同。

  该收集器是server模式下的新生代默认收集器,除了Serial,只有它能够和CMS收集器配合工作。

  2.3Parallel Scavenge

  特点:是一个新生代收集器,使用复制算法,并行和多线程收集器,它会尽可能的缩短垃圾回收时用户线程的停顿时间,目标是达到一个可控制的吞吐量,所谓吞吐量是cpu运行用户代码的时间和cpu总消耗时间的比值,该收集器被称为”吞吐量“优先的收集器,另外该收集器还有一个-XX:+UseAdaptiveSizePolicy,用来自动调节新生代的大小,,自适应调节策略也是与ParNew的主要的区别。

  2.4Serial Old收集器

  Serial Old是Serial的老年代版本,采用”标记-整理“算法进行垃圾回收,被client下的虚拟机使用,在Server模式下:一个用途是和jdk1.5之前的版本中Parallet Scavenge收集器搭配使用,另外一个用户就是作为CMS收集器的后备预案。

  2.5Parallel Old 收集器

  该收集器是parallel Scavenge收集器的老年代版本,使用多线程和”标记整理“算法。

  主要是为了与Parallel Scavenge配合使用,如果新生代选择了Parallel Scavenge收集器,那么老年代除了Serial Old外别无选择,单线程的Serial old在服务器性能上会严重下降。

  2.6 CMS 收集器

  CMS(concurrent mark Sweep)是一种以获取最短回收停顿时间为目标的收集器,该收集器复杂一点,收集时候分为以下四步:

  1>初始标记。

  2>并发标记。

  3>重新标记。

  4>并发清除。

  初始标记和重新标记这两个过程仍然要停止用户线程,重新标记是为了修正在初始标记和用户线程同时执行新产生的需要被清除的对象,这两个过程很快,主要的耗时是并发标记和并发清除中。

  该收集器有三个缺点:

  1>对cpu敏感。cms默认开启的回收线程数目为(cpu数量+3)/4,如果cpu过多会导致用户感到突然停顿。

  2>cms无法处理浮动垃圾。由于cms并发清理阶段用户线程还在不断地运行,这一部分垃圾可能出现在标记之后,cms无法处理他们,只好在下一次进行一次处理。

  3>cms是基于“标记-清除”算法,可能会产生大量的内存碎片。

  2.7 G1收集器

  在jdk1.6 update14中提供了一个使用版本,与前面的cms相比,他是基于“标记-整理”算法,不会产生内存碎片,另外他可以精确的控制停顿,让垃圾回收不超过N毫秒,另外他还可以在不牺牲吞吐量的情况下完成低停顿的垃圾回收,这是因为它会避免在全区域进行垃圾回收,g1会将整个java堆划分为多个大小固定的独立区域,并根据这些垃圾的堆积程度,在后台维护一个垃圾优先列表,,优先回收垃圾最多的区域。 达内科技

资源下载