深入理解JVM03--垃圾收集算法(“标记-清除”,“复制”,“标记-整理”,“分代收集”)

本文是基于周志明的《深入理解Java虚拟机》

垃圾收集算法
    Java 语言的一大特点就是可以进行自动垃圾回收处理,而无需开发人员过于关注系统资源,例如内存资源的释放情况。自动垃圾收集虽然大大减轻了开发人员的工作量,但是也增加了软件系统的负担。
    由于垃圾收集算法的实现涉及大量的程序细节,而且各个平台的虚拟机操作内存的方法各不相同,因此下面只讨论几种算法的思想。

1、标记-清除算法 (Mark-Sweep)

    是最基础的收集算法,之所以这么说,是因为下面的其它算法都是基于这种思路并对其不足进行改进而得到的。
  
   标记-清除算法 将垃圾回收分为两个阶段:
    ①.标记阶段:首先标记出所有需要回收的对象。
    如何标记,查看这篇博客 http://blog.csdn.net/ochangwen/article/details/51406779
    ②.清除阶段:标记完成后,统一回收被标记的对象

   缺点:
    ①.效率问题:标记清除过程效率都不高。
    ②.空间问题:标记清除之后会产生大量的不连续的内存碎片(空间碎片太多可能会导致以后在程序运行过程中需要分配较大的对象时,无法找到足够的连续的内存空间而不得不提前触发另一次垃圾收集动作。)
-------------------------------------------------------------------------------------------------------------------

2、复制算法 (Copying)

  2.1.算法思想:
    1).将现有的内存空间分为两快,每次只使用其中一块.
    2).当其中一块时候完的时候,就将还存活的对象复制到另外一块上去。
    3).再把已使用过的内存空间一次清理掉。

  2.2.优点:
    1).由于是每次都对整个半区进行内存回收,内存分配时不必考虑内存碎片问题。
    2).只要移动堆顶指针,按顺序分配内存即可,实现简单,运行高效。
     
   2.3.缺点:
    1).内存减少为原来的一半,太浪费了。
    2).对象存活率较高的时候就要执行较多的复制操作,效率变低。
    3).如果不使用50%的对分策略,老年代需要考虑的空间担保策略。

   2.4.演进
    并不需要根据1:1划分内存空间,而是将内存划分为一块较大的EdenSpace和两块较小的SurvivorSpace
JavaHeap内存回收模型( 当前商业虚拟机大多使用此算法回收新生代


---------------------------------------------------------------------------------------------------------------------------

3、标记-压缩算法 (Mark-Compact)

    由于复制算法的缺点,及老年代的特点(存活率高,没有额外内存对其进行空间担保),老年代一般不使用复制算法。

  3.1.算法思想
    1).标记阶段:首先标记出所有需要回收的对象。与“标记-清除”一样
    2).让存活的对象向内存的一段移动。而不跟“标记-清除”直接对可回收对象进行清理
    3).再清理掉边界以外的内存。   
  由于老年代存活率高,没有额外内存对老年代进行空间担保,那么老年代只能采用标记-清理算法或者标记整理算法。
 -------------------------------------------------------------------------------------------------------------------------

4、分代收集算法 (Generational Collecting)

    当前的商业虚拟机的垃圾收集都采用,把Java堆分为新生代和老年代。根据各个年代的特点采用最适当的收集算法。
     在新生代中 ,每次垃圾收集时都发现有大批对象死去,只有少量存活,选用:复制算法
     在老年代中 因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清除”或者“标记-整理”算法来进行回收。

猜你喜欢

转载自blog.csdn.net/c880420/article/details/80612609