【JVM】垃圾收集2-垃圾收集算法

大部分内容转自https://zhuanlan.zhihu.com/p/25539690
作者:韦庆明

垃圾收集算法(4种)

  为了更好的提高GC的性能HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to),默认比例为8:1。
关于Eden与Survior的解释请看:https://blog.csdn.net/lojze_ly/article/details/49456255

一、标记-清除算法

【JVM】垃圾收集2-垃圾收集算法_第1张图片
  标记-清除算法采用从根集合进行扫描,对存活的对象进行标记,标记完毕后,再扫描整个空间中未被标记的对象进行直接回收,如上图。
  标记-清除算法不需要进行对象的移动,并且仅对不存活的对象进行处理,在存活的对象比较多的情况下极为高效,但由于标记-清除算法直接回收不存活的对象,并没有对还存活的对象进行整理,因此会导致内存碎片。

  • 缺点:
    • 1.效率问题 -标记和清除的过程效率并不高 (递归与全堆对象遍历)
    • 2.空间问题 -标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致,当程序在以后的运行过程中无法找到足够的连续内存不得不提前触发另一次的GC动作。

二、复制算法(常用回收新生代)

【JVM】垃圾收集2-垃圾收集算法_第2张图片
  复制算法将内存划分为两个区间,使用此算法时,所有动态分配的对象都只能分配在其中一个区间(活动区间),而另外一个区间(空间区间)则是空闲的。
  复制算法采用从根集合扫描,将存活的对象复制到空闲区间,当扫描完毕活动区间后,会的将活动区间一次性全部回收。此时原本的空闲区间变成了活动区间。下次GC时候又会重复刚才的操作,以此循环。
  复制算法在存活对象比较少的时候,极为高效,但是带来的成本是牺牲一半的内存空间用于进行对象的移动。所以复制算法的使用场景,必须是对象的存活率非常低才行,而且最重要的是,我们需要克服50%内存的浪费。

三、标记-整理算法(常用回收老年代)

【JVM】垃圾收集2-垃圾收集算法_第3张图片
  标记过程与标记清除类似,但后续步骤不是直接对可回收对象进行清理,让所有存活对象都向一端移动,然后清理掉端边界以外的内存。
  标记-整理 算法是在标记-清除算法之上,又进行了对象的移动排序整理,因此成本更高,但却解决了内存碎片的问题。

四、分代收集算法

  这种算法只是根据对象存活周期不同将内存区域划分为几块,一般是把JAVA堆分为新生代和老年代。

  • 新生代 :新生代每次垃圾收集是都发现有大批对象死去,只有少量存活,所以对于新生代采用复制算法,只需要付出少量存活对象的复制成本就可以完成收集
  • 老年代 :因老年代对象存活率高,则使用标记清理标记整理算法来回收

  JVM为了优化内存的回收,使用了分代回收的方式,对于新生代内存的回收(Minor GC)主要采用复制算法。而对于老年代的回收(Major GC),大多采用标记-整理算法

你可能感兴趣的:(JVM学习)