从如何判定对象消亡的角度出发(例如,前面提到的引用计数算法和GC Roots可达性分析算法),垃圾收集算法可以划分为:
这两类也常被称作“直接垃圾收集”和“间接垃圾收集”
当前商业虚拟机的垃圾收集器实现大多遵循“分代收集(Generational Collection)”理论,该理论包含三条分代假说:
依据“弱分代假说”和“强分代假说”,在兼顾垃圾收集器的时间开销和内存空间的有效利用的基础上,设计者将对象依据其存亡特征的不同的放在不同的区域中(一般至少将Java堆划分成了“新生代”和“老年代”),因而才有“Minor GC”、“Major GC"、“Full GC”这样回收类型的划分,也才能够针对不同内存区域安排与里面存储对象存亡特征相匹配的垃圾收集算法(“标记-复制算法”、“标记-清除算法”、“标记-整理算法”等)
依据“跨代引用假说”,设计者不再需要针对跨代引用的内存回收在固定的GC Roots之外,再额外遍历整个老年代中所有对象来确保可达性分析结果的正确性;而仅需再新生代上建立一个全局的数据结构(一般称之为“记忆集”,Remembered Set),标识出老年代的哪一块内存会存在跨代引用,当发生Minor GC时,只有包含了跨代引用的小块内存里的对象才会加入到GC Roots进行扫描
根据垃圾收集动作是否覆盖整个堆和方法区,GC分为部分收集(Partial GC)和整堆收集(Full GC),而部分收集又可细分为新生代收集(Minor GC、Young GC)、老年代收集(Major GC、Old GC)、混合收集(Mixed GC)
标记-清除算法,一种非移动式的回收算法(较于后面将会提到的标记-整理算法),算法分为“标记”和“清除”两个阶段:首先标记出所有需要回收的对象,在标记完成后,统一回收所有被标记的对象,也可以反过来,标记存活的对象,统一回收未被标记的对象
缺点:
标记-复制算法,为解决标记-清除算法存在的面对大量可回收对象时执行效率低的问题,采用“半区复制”的方式:将可用内存按容量划分为大小相等的两块,每次只使用其中一块,当这一块用完后,就将存活的对象复制到另一块区域上,而后将已使用的内存空间一次性清理掉
缺点:
现代商用的Java虚拟机大多采用这种方式进行新生代的回收,依据“弱分代假说”所划分出来的“新生代”中的对象大多朝生夕灭,减少了因大量存活对象导致的复制迁移的开销
同时,还是依照“朝生夕灭”的特征,又出现了解决内存划分不合理导致内存浪费问题的“Appel式回收”:将新生代采用8:1的比例划分成一块较大的Eden区和两块Survivor空间,每次分配内存只使用Eden和其中一块Survivor,发生垃圾收集时,将Eden和Survivor中仍然存活的对象一次性复制到另外的一块Survivor空间上,然后直接清理掉Eden和已用过的那块Survivor空间
此外,“Appel式回收”对分配担保也做了安全设计:当Survivor空间不足以容纳一次Minor GC之后存活的对象时,将依赖老年代,即这些对象将通过分配担保机制直接进入老年代
标记-整理算法,一种移动式的回收算法(较前面提到过的标记-清除法),是针对老年代对象存放特征设计出的一套算法:其中标记过程仍与标记-清除算法一致,区别在于,标记-整理法并不直接清理可回收对象,而是让所有存活对象都向内存空间一端移动,而后,将边界之外的内存回收掉
标志-整理法,由于“整理”的需要,存在对象移动,对于老年代这种有大量存活的对象的内存区域来说,移动对象就意味着需要更新所有引用这些对象的地方,这种操作则不得不在被称为“Stop The World”的全程暂停用户应用程序的情况下进行,因此造成了用户应用程序一定程度的延迟
同标记-清除算法比较一下,由于没有“整理”的动作,弥散于堆中的存活对象导致的空间碎片话问题就只能依赖更为复杂的内存分配器和内存访问器来解决(类似于硬盘通过分区表实现存储大文件不需要使用物理连续的内存空间),这势必会直接影响应用程序的吞吐量
对比两种算法,是否移动对象都存在弊端:从内存的使用角度看,移动则内存回收时复杂,不移动则内存分配复杂;从垃圾收集的停顿时间看,不移动对象停顿时间更短,甚至不需要停顿,不移动对象则吞吐量较高
因此,HotSpot虚拟机里,关注吞吐量的Parallel Scavenge收集器是基于标记-整理算法的,而关注延迟的CMS收集器则是基于标记-清除算法的
另外,CMS还提供了一种“和稀泥式”的配置参数,可以不再内存分配和访问上增加太大负担,做法是:让虚拟机平时大多数时间都采用标记-清除算法,暂时容忍内存碎片,当内存碎片化程度达到一定比例时,再采用标记-整理算法收集一次,以便获得更规整的内存空间
缺点:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。