垃圾回收算法


标记-清楚算法(Mark and Sweep)

  • ???? 标记:从根集合进行扫描,对存活的对象进行标记。
  • ???? 清除:对堆内存从头到尾进行线性遍历,回收不可达对象内存
    -垃圾回收算法
  • 在Mark阶段 根对象可以访问b,b又可以访问e,故be都是可到达对象,同理f,g,j,k都是可达对象
  • 未被标记未可达对象的都会被清除

????意:在垃圾回收阶段,应用程序的执行会暂停,等待回收执行完毕后,再恢复程序的执行。

不足:碎片化(如图所示,A,C,D,I被清除了,内存空间不在连续的内存碎片,内存碎片太多会导致以后在程序运行过程中需要分配较大的内存时,不得不再次的进行垃圾回收,程序会暂停,垃圾回收一直在回收垃圾,最后会导致内存溢出)

复制算法(Copying)

  • ???? 分为对象面和空闲面
  • ???? 对象在对象面创建
  • ???? 存活的对象被从对象面复制的空闲面 (当定义为空闲面的内存快用完的时候,会把存活的对象复制到空闲面)
  • ???? 将对象面所有内存清楚

优点:

  • ???? 解决了碎片化问题
  • ???? 顺序分配内存,简单高效
  • ???? 适合用于对象存活率低的场景

缺点:

  • 若对象存活率较高的场景,就会进行较多的复制操作,效率会很低
  • 更关键的是,如果不想浪费50%的空间,就需要有额外的空间进行分配担保,以应对被使用的内存中所有对象都100%存活的极端情况,所以在老年代一般不能直接选用这种算法

标记-整理算法(Compacting)

  • ???? 标记:从根集合进行扫描,对存活的对象进行标记。
  • ???? 清除:移动所有存活的对象,且按照内存地址以此排序,然后将末端内存地址以后的内存全部回收
    垃圾回收算法
    会将没有标记的对象清除,然后所有存活的对象向一端移动,然后清理掉末端内存地址以外的内存

优点:

  • ???? 避免内存的不连续性
  • ???? 不用设置两块内存互换
  • ???? 适用于存活率较高的场景

分代收集算法(Generational Collector)

  • ???? 垃圾回收算法的组合拳
  • ???? 按照对象生命周期的不同划分区域以采用不同的垃圾回收算法

GC 的分类

  • Minor GC
  • Full GC

年轻代:尽可能快速收集掉那些生命周期短的对象

  • Eden 区
  • 两个Survivor区

HotSpot JVM把年轻代分为了三部分:1个Eden区和2个Survivor区(分别叫from和to)。默认比例为8:1,新创建的对象一般都会放在Eden区域,大对象特殊处理,经历过一次Minor GC 后,若还存活会放到幸存区,在经历Minor GC很多次后会存放到老年区


对象如何晋升到老年代

  • ???? 经历一定Minor GC次数依然存活的对象

  • ???? Survivor 区中存放不下的对象

  • ???? 新生成的大对象(-XX:+PretenuerSizeThreshold )(超过这个size就会放入老年代)


常用的调优参数

  • -XX:SurvivorRatio: Eden和Survivor的比值,默认时8:1

  • -XX:NewRatio:老年代和年轻代内存大小的比例

  • -XX:+MaxTenuringThreshold:对象从年轻代晋升到老年代经过gc次数的最大阈值


    老年代:存放生命周期较长的对象

    • 触发Full GC的条件
      • 老年代空间不足
      • 永久代空间不足
      • CMS GC时出现promotion failed和concurrent mode failure
      • System.gc()方法的调用
      • 统计得到的Minor GC晋升到旧生代的平均大小大于老年代的剩余空间

相关文章:

  • 2021-07-31
  • 2022-01-22
  • 2021-05-06
  • 2021-05-27
  • 2021-10-16
猜你喜欢
  • 2021-10-08
  • 2021-11-10
  • 2021-06-23
  • 2021-09-09
  • 2022-01-16
  • 2022-03-06
  • 2022-03-02
  • 2022-01-15
相关资源
相似解决方案