java中的垃圾回收算法与垃圾回收器

常用的垃圾回收算法标记-清除标记清除算法是一种非移动式的回收算法 , 分为标记 清除 2个阶段 , 简而言之就是先标记出需要回收的对象 , 标记完成后再回收掉所有标记的内存对象 , 如下图

java中的垃圾回收算法与垃圾回收器

文章插图
可见回收后图中被标记的对象被删除回收了 , 但是碎片化比较严重不连续 对于下次分配大对象的时候由于内存不连续性影响比较大 , 而且每一次Gc的时候需要执行2个操作 1次标记 1次回收
标记-整理压缩标记整理压缩算法是一种移动式的算法 , 由于上面标记清除算法导致内存不连续的问题 标记-整理算法就解决了这个问题 。
java中的垃圾回收算法与垃圾回收器

文章插图
工作原理也是2阶段操作而且更复杂了 , 首先找出(root)根地址的对象一直寻找标记是否被引用 , 引用了就标记一下 , 标记完成后把标记的对象按顺序移动排列在一起并清除掉边界的未标记的对象 , 这样就没有内存碎片 。
缺点
  • 由于标记完成后需要移动对象 移动的过程可能会产生STW
  • 2次+调整指针
复制算法复制算法更粗暴了 , 逻辑也很简单 通常直接申明了2块一样大小存储空间 , 每次只使用其中1块空间 , 当使用的这块空间不够用的时候就触发回收操作 , 将存活的对象copy到另一块空间中按顺序存放 , 可回收的就回收删除掉 , 这样一来就不会出现内存碎片 , 但是要多浪费50%的内存空间 , 主要用于年轻代 比如s0 s1亦是如此 。
java中的垃圾回收算法与垃圾回收器

文章插图
分代回收算法根据对象的存活周期划分为新生代、老年代 。因此可以根据不同年代的特点使用不同的回收算法 。分代收集目前是大部分JVM
  • 新生代特点
    在新生代中大量的对象产生 又有大量的对象需要销毁 , 他们存活时间都比较短 。基本上都是回收的时候大部分会被回收掉 , 只有少量的对象是存活不回收的 。
    存活对象少 , 垃圾对象多这就比较适合使用复制算法 , 复制算法需要用到2块内存空间 每次只使用其中一块 , 在jdk8中不只是单纯的划分为s0 s1 二块存储空间 , 还新增了一块Eden ,s0 s1的默认大小是eden的8/1 这样设计的目的在于每次触发回收的时候把90(eden+其中1个s区)的区域中存活的对象copy到10%的存储中 , 理论上清除了90%的空间 , 这样做的好处就是不需要花50%的存储空间 , 只浪费了10%的空间就实现了这个算法逻辑 。
  • 老年代特点
    老年代的特点就是对象存活时间都比较长 , 大量的存活对象就不适合像新生代一样用复制算法了 因为copy的成本太高 , 这种就比较适合标记清除算法 , 或者标记清除整理算法 。
    优缺点概述
    算法名称优点缺点标记-清除简单位置不联系 碎片化严重 效率低 2次扫描标记-压缩整理没有碎片效率低 2次扫描 可能会多次重置指针复制算法没有碎片 简单高效浪费空间
垃圾回收器上面的垃圾算法仅仅只是一个理论上的算法  , 正在实现这些算法的叫垃圾回收器 , 在工作中具体是怎么回收工作的可以不关心 , 但是需要了解不同的垃圾回收器是基于哪种算法实现的 , 有助于出现性能问题的时候有思路去参数调优 , 而不是盲目的问度娘 。各个年轻代 老年代垃圾回收器可组合配对方式如下图所示

经验总结扩展阅读