jvm

JVM 系列 垃圾收集算法

开启JVM探索新篇章

Posted by lichao modified on November 7, 2019

算法

新生代收集算法

使用 标记-复制收集 算法来回收新生代。将内存分为一块较大的eden空间和两块较小的 survivor 空间,每次使用eden和其中一个survivor空间。当回收时,将eden和survivor中还存活着的对象一次性的复制到另外一块 survivor 空间上,最后清理掉 eden 和刚才用过的 survivor 空间。

Hotspot 虚拟机默认的 eden 和 servivor 的大小比例是 8:1,也就是每次新生代中可用内存空间为整个新生代容量的 90%。当servitor空间不够用时,需要依赖其他内存(老年代)进行担保。

老年代算法

标记-清除算法

首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。

后续的收集算法都是基于这种思路并对其不足进行改进而得到的。

缺点

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

标记-复制算法

将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。

将内存缩小为了原来的一半。

优点

标记-整理算法

首先标记,然后让所有存活的对象都向一端移动。然后清理掉端边界之外的内存。

场景

适用于老年代中,存在大量的存活对象需要复制。

分代收集算法

现代的垃圾收集器基本都是采用分代收集算法,其主要思想: 将 Java 的堆内存逻辑上分成两块:新生代、老年代,针对不同存活周期、不同大小的对象采取不同的垃圾回收策略 存储概览

  • 新生代(Young Generation)

新生代又叫年轻代,大多数对象在新生代中被创建,很多对象的生命周期很短。每次新生代的垃圾回收(又称Young GC、Minor GC、YGC)后只有少量对象存活,所以使用复制算法,只需少量的复制操作成本就可以完成回收。

新生代内又分三个区:一个Eden区,两个Survivor区(S0、S1,又称From Survivor、To Survivor),大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到两个Survivor区(中的一个)。当这个Survivor区满时,此区的存活且不满足晋升到老年代条件的对象将被复制到另外一个Survivor区。对象每经历一次复制,年龄加1,达到晋升年龄阈值后,转移到老年代

  • 老年代(Old Generation)

在新生代中经历了N次垃圾回收后仍然存活的对象,就会被放到老年代,该区域中对象存活率高。老年代的垃圾回收通常使用“标记-整理”算法