四种回收算法
标记清除
标记后,将未标记到的对象实例,其内存清除,同时维护可用内存列表,之后基于此进行分配内存。
优点:速度快
缺点:内存碎片化严重,基于可用内存列表分配内存,多了一步维护操作
标记复制
- 内存划为两块等大小,使用一块内存进行分配,GC时,将标记到的对象复制到另一块内存中。
- 居于新生代一次回收率大概率会达到90%以上。 依次可优化为 8:1:1的空间进行处理,以避免一半空间被浪费的情况。 只浪费十分之一的空间,如果空间1无法装下所有存活对象,则将剩余的直接进入老年代,由老年代兜底。 8:1:1 比例是可调整的
优点:速度尚可,且收集后,内存空间是整齐的。
缺点:浪费一部分空间。 8:1:1 也会出现空间不够情况,导致老年代膨胀
现在的新生代收集器 都是使用8:1:1的处理方式
标记整理
标记后,将标记到的对象都逐个往前移动,最终指针前面的都为存活对象,后面的内存都为可重新分配内存
优点:自带整理,且不浪费空间
缺点:速度慢,需要移动大量内容
分代收集
根据CG年龄分代,基分为新生代、老年代。 基于经历过多次GC的对象,理论还会活得很久。 将被回收概率小的对象移动到老年代。 这样新生代和老年代可以针对其不同的特性使用不同的算法。
新生代:一般使用标记复制算法
老年代:一般使用标记清除 或 标记整理算法
七个成熟的收集器
Serial
单线程收集 新生代
标记复制
Serial Old
单线程收集 老年代
标记整理
ParNew
多线程收集 新生代
标记复制
CMS
多线程收集 老年代 标记清除
进行快速标记 - 收集线程与运行线程并行运行
更多的关注减少JVM停顿时间,但是消耗的资源会更多,同时也会有浮动垃圾的情况
Parallel Scavenge
多线程收集 新生代 标记复制
更多的关注吞吐量,期望整体占用更少的cpu比例
同时吞吐量关注,和JVM停顿时间。可以配置具体的参数,让收集器更倾向于设定的配置。
其动态的自主调整的能力,根据运行时收集到的数据,进行自适应的配置,以期达到最好的效果。
Parallel Old
多线程收集 老年代 标记整理
G1
新生代的收集器,集老年代和新生代收集为为一体。 不再是简单的将老年代、新生代分开。
一般的组合
Serial + Serial Old
串行收集器
在资源少,如客户端机器,使用串行收集器,占用更少的资源。
ParNew + CMS + Serial Old
并行收集器
追求响应时间, 会占用更多的cpu资源
Parallel Scavenge + Parallel Old
并发收集器 | Jdk7 、Jdk8默认收集器
追求吞吐量
G1 单独使用
Jdk 9 默认收集器
新一代的收集器,取代 ParNew + CMS + Serial Old