分为标记和清除两个阶段:首先标记所有需要回收的对象,在标记完成后统一回收被标记的对象。
主要不足:
将内存划分成大小相等的两块,每次只使用其中的一块。当这一块内存用完了,就将还存活着的对象复制到另一块上面,然后再把已使用过的那块内存一次性的清理掉。
改善办法:IBM公司研究表明98%的对象都是“朝生暮死”的。所以不需要按1:1分配空间,而是将内存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden和一块Survivor。当回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor中,然后清理掉原来的内存。通常Eden和Survivor的空间比例为8:1。
当然,没有办法保证每次回收都只有不到10%的对象存活,当Survivor空间不够用时,需要依赖其他内存(年老代)进行分配担保----如果Survivor没有足够的空间收集存活的对象,这些对象直接进入年老代。
标记过程和标记清理法过程相同,但后续步骤不直接进行清除,而是让所有对象都像一端移动,然后直接清理掉端边界以外的内存。
根据对象的存活周期将内存分为几块,Java一般分为新生代和年老代,这样就可以根据各个代的不同特点采用最合适的收集算法。一般新生代采用复制算法,年老代采用标记清除法或标记整理法。
枚举根结点:使用准确式GC进行根结点收集,HotSpot中是用一组称为OopMap实现的。
安全点:程序执行时不是在所有地方都可以停下来进行GC,只有在达到安全点时才能暂停。在GC发生时让所有线程都在安全点暂停有两种方式:抢先式中断和主动式中断。
安全区域:安全区域是指在一段代码中,引用关系不会发生变化。在这个区域中的任何地方开始GC都是安全的。