垃圾收集算法

垃圾收集算法

1、分代收集理论

目前主流JVM虚拟机中的垃圾收集器,都遵循分代收集理论

  • 弱分代:绝大多数对象都是朝生夕灭
  • 强分代:经历越多次垃圾收集过程的对象,越难以回收,难以消亡

按照分代收集理论设计的“分代垃圾收集器”,所采用的设计原则:收集器应该将Java堆划分成不同的区域,然后将回收对象依据其年龄(年龄即对象经历过垃圾收集过程的次数)分配到不同的区域存储

(1)分代存储
  • 如果一个区域中大多数对象都是朝生夕灭(新生代),难以熬过垃圾收集过程的话,把它们集中存储在一起,每次回收时,只关注如何保留少量存活对象,而不是去标记大量将要回收的对象,就能以较低代价回收到大量的空间。
  • 如果一个区域中大多数对象都是难以回收(老年代),那么把它们集中放在一起,JVM虚拟机就可以使用较低的频率,来对这个区域进行回收。
  • 这样设计的好处是,兼顾垃圾收集的时间开销和内存空间的有效利用。
(2)分代收集

堆区按照分代存储的好处:

Java堆区划分成不同区域后,垃圾收集器才可以每次只回收其中某一个或者某些区域,所以才有MinorGCMajorGCFullGC等垃圾收集类型划分。

Java堆区划分成不同区域后,垃圾收集器才可以针对不同的区域,安排与该区域存储对象存亡特征相匹配的垃圾收集算法:标记-复制算法标记-清除算法标记-整理算法

垃圾收集类型划分:

  • 部分收集(Partial GC):没有完整收集整个Java堆的垃圾收集,其中又分为:

    • 新生代收集(Minor GC / Young GC
    • 老年代收集(Major GC / Old GC
    • 混合收集(Mixed GC):收集整个新生代和部分老年代的垃圾收集。
  • 整堆收集(Full GC):收集整个Java堆的垃圾收集

垃圾收集算法_第1张图片

2、垃圾收集算法

(1)标记-清除算法(Mark-Sweep)

最基础的收集算法

算法实现思路
  1. 该算法分为“标记”和“清除”阶段
  2. 首先标记出所有不需要(或需要)回收的对象
  3. 标记完成后,清除所有没有(或有)被标记的对象
存在的问题
  1. 执行效率不稳定

    如果执行垃圾收集的区域,大部分对象是需要被回收的,则需要大量的标记和清除动作,导致效率变低

  2. 内存空间碎片化

    标记清除后会产生大量的不连续的内存空间碎片,会导致分配较大对象时,无法找到祖足够的连续空间,从而会触发新的垃圾收集动作

垃圾收集算法_第2张图片

(2)标记-复制算法(Copying)
算法实现思路

简称 “复制算法” ,为了解决“标记-清除”面对大量可回收对象时执行效率低下的问题

  1. 将内存分为两个大小相同的空间,每次使用其中的一块
  2. 当其中一块内存使用完成后,就将还存活的对象复制到另一块,然后清空当前已经使用的空间
算法特点

当内存中大多数对象都是可回收的情况,推荐使用此算法

存在的问题
  1. 对象存活率较高,需要进行较多的内存间复制,效率降低
  2. 浪费过多的内存,使现有的可用空间变为原来的一半

垃圾收集算法_第3张图片

3、标记-整理算法(Mark-Compact)
算法实现思路

标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象回收,而是让所有存活的对象向内存空间一端移动, 然后直接清理边界以外的内存,这样清理的机制,不会像标记-清除那样留下大量的内存碎片。

垃圾收集算法_第4张图片

4、总结

当前虚拟机的垃圾收集都基于分代收集思想,根据对象存活周期的不同,将内存分为几个不同的区域,在不同的区域选择使用合适的垃圾收集算法

  • 在新生代中,每次收集都会有大量垃圾对象被回收,所以可以选择“标记-复制”算法,只需要付出少量对象的复制成本就可以完成每次垃圾收集
  • 在老年代中,对象存活几率是比较高的,而且没有额外的空间对它进行分配担保,所以选择“标记-清除”或“标记-整理”算法进行垃圾收集

你可能感兴趣的:(算法,jvm,java)