分为“标记”和“清除”两个阶段。首先标记出全部须要回收的对象,在标记完成后统一回收全部被标记的对象。 存在如下两个问题:git
将内存划分为大小相等的两块,每次只使用其中一块,当这一块内存用完了就将还存活的对象复制到另外一块上面,而后再把使用过的内存空间进行一次清理。github
如今的商业虚拟机都采用这种收集算法来回收新生代,可是并非将新生代划分为大小相等的两块,而是分为一块较大的 Eden 空间和两块较小的 Survivor 空间,每次使用 Eden 空间和其中一块 Survivor。在回收时,将 Eden 和 Survivor 中还存活着的对象一次性复制到另外一块 Survivor 空间上,最后清理 Eden 和使用过的那一块 Survivor。算法
HotSpot 虚拟机的 Eden 和 Survivor 的大小比例默认为 8:1,保证了内存的利用率达到 90%。若是每次回收有多于 10% 的对象存活,那么一块 Survivor 空间就不够用了,此时须要依赖于老年代进行分配担保,也就是借用老年代的空间存储放不下的对象。jvm
根据老年代的特色特出的一种标记算法,标记过程仍然与“标记-清除”算法同样,但后续步骤不是直接对可回收对象回收,而是让全部存活的对象向一端移动,而后直接清理掉端边界之外的内存。cdn
如今的商业虚拟机采用分代收集算法,它根据对象存活周期将内存划分为几块,不一样块采用适当的收集算法。对象
通常将堆分为新生代和老年代。在新生代中,每次收集都会有大量对象死去,因此能够选择复制算法,只须要付出少许对象的复制成本就能够完成每次垃圾收集。而老年代的对象存活概率是比较高的,并且没有额外的空间对它进行分配担保,因此咱们必须选择标记-清除或标记-整理算法进行垃圾收集。blog
参考资料内存