垃圾收集算法

标记-清除算法(Mark-Sweep):首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
标记方式参考《判断对象是否存活》
标记-清除算法是最基础的收集算法,因为后续的收集算法都是基于这种思路并对其不足进行改进而得到的,主要不足有两点:
(1) 效率低,标记和清除两个过程的效率都不高;
(2) 空间问题,标记清除后会产生大量不连续的内存碎片,可能会导致后续要分配较大内存时触发另一次垃圾回收;

复制算法(Copying):将总内存平分成两块一样大的内存A和B,先在A上进行内存分配,当这块内存用完时,就将A上还活着的所有对象复制到B上,然后清除所A上的所有对象,后续直接在B上分配内存,依次轮换。
IBM专业研究表明,新生代中的对象98%是“朝生夕死”的,所以并不需要按照1:1来分配内存,而是直接分为8:1:1即可,8称之为Eden区,两个1称之为Survivor,每次使用Eden和其中一块Survivor,当回收时,将Eden和Survivor中还存活中的对你一次性地移到另一块Survivor中,最后清理后Eden和刚才用过的Survivor空间。
当然,并不是每次都是98%的内存都可回收,我们无法保证每次回收都只有不多于10%的对象存活,当Survivor空间不够用时,需要依赖其他内存(这里指老年代)进行分配担保,即如果另一个Survivor空间不足时,将这些对象直接通过分配担保机制进入老年代。

标记-整理算法(Mark-Compact):与标记-清除算法一样的标记方法,只不过最后不是统一回收,而是把还活着的对象都移到一起,然后直接清理掉边界以外的所有内存。


分代收集算法(Generational Collection):当前商业虚拟机的垃圾收集都采用了分代收集算法,这种算法是根据对象存活周期的不同,将内存划为几块,一般是把Java堆分为新生代和老年代,在新生代由于每次收集时都会有大批量的对象死去,因此使用复制算法;而老年代中因为对象存活率高、没有额外的空间对它进行分代担保,因此采用标记-清除或标记-整理算法。

你可能感兴趣的:(深入理解Java虚拟机)