算法
新生代收集算法
使用 标记-复制收集 算法来回收新生代。将内存分为一块较大的eden空间和两块较小的 survivor 空间,每次使用eden和其中一个survivor空间。当回收时,将eden和survivor中还存活着的对象一次性的复制到另外一块 survivor 空间上,最后清理掉 eden 和刚才用过的 survivor 空间。
Hotspot 虚拟机默认的 eden 和 servivor 的大小比例是 8:1,也就是每次新生代中可用内存空间为整个新生代容量的 90%。当servitor空间不够用时,需要依赖其他内存(老年代)进行担保。
老年代算法
标记-清除算法
首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
后续的收集算法都是基于这种思路并对其不足进行改进而得到的。
缺点
- 效率问题:标记和清除两个过程的效率都不高。
- 空间问题:标记清除之后会产生大量不连续的内存碎片,空间碎片太多会导致以后在程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作。
标记-复制算法
将可用内存按容量划分为大小相等的两块,每次只使用其中的一块。当这一块的内存用完了,就将还存活着的对象复制到另外一块上面,然后再把已使用过的内存空间一次清理掉。
将内存缩小为了原来的一半。
优点
标记-整理算法
首先标记,然后让所有存活的对象都向一端移动。然后清理掉端边界之外的内存。
场景
适用于老年代中,存在大量的存活对象需要复制。
分代收集算法
现代的垃圾收集器基本都是采用分代收集算法,其主要思想: 将 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次垃圾回收后仍然存活的对象,就会被放到老年代,该区域中对象存活率高。老年代的垃圾回收通常使用“标记-整理”算法