Java垃圾收集器
收集算法是内存回收的方法论,垃圾收集器是内存回收的实践者。《Java虚拟机规范》中对垃圾收集器应该如何实现并没有做出任何规定,因此不同的厂商,不同版本的虚拟机所包含的垃圾是收集器可能会差别很大。
新生代
Serial
- 标记-复制算法
- 单线程
- 适用于运行在客户端模式下的虚拟机
- 配合的老年代收集器:CMS,Serial Old(MSC)
ParNew (重点关注)
- 多线程版本的 Serial
- 标记-复制算法
- jdk1.7之前首选新生代收集器
- 配合的老年代收集器:CMS,Serial Old(MSC)
- 使用 -XX:+UseConcMarkSweepGC设置-XX:+UseParNewGC自动启用 。因此, 如果不需要平行年轻代GC,则需要通过设置-XX:-UseParNewGC来禁用
- JDK9开始,ParNew 加 CMS 收集器的组合就不再推荐了,取代的是G1垃圾收集器
- 官方目前已取消了 -XX:+UseParNewGC,意味着ParNew 加 Serial Old 以及Serial 加CMS 这两组收集器器的组合。意味着 ParNew 和 CMS 从此只能互相搭配使用,再也没有其他收集器能够和他们配合了
- 缩短垃圾收集时用户线程的停顿时间
Parallel Scavenge(吞吐量优先)
- 标记复制算法
- 并行收集的多线程收集器 Parallel Scavenge
- CMS 收集器关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量。吞吐量 = 运行用户代码时间/(运行用户代码时间 + 运行 垃圾收集器时间)
- 控制垃圾收集停顿时间(-XX:MaxGCPauseMillis)收集器尽力保证内存回收的时间不超过用户设定值。如果设定的太小,会导致垃圾回收更频繁。
- 控制吞吐量的参数(-XX:GCTimeRatio)
- 搭配老年代 Parallel Old (吞吐量优先)
老年代
Serial Old 收集器
- 单线程
- 标记-整理算法
Parallel Old 收集器
- 多线程并行收集
- 标记-整理算法
- 吞吐量优先
CMS 收集器(重点关注)
- 一种获取最短回收停顿时间为目标的收集器
- 大部分Java 应用几种在互联网网站或者浏览器的B/S系统的服务器上,这类应用通常都会较为光之服务的响应时间,系统系统停顿时间尽可能短,以给用户带来良好的交互体验
- 基于标记-清除算法
- 分为四个步骤:1)初始标记(CMS initial mark ,会 stw)2)并发标记 (CMS concurrent mark)3)重新标记(CMS remark ,会stw)4)并发清除
步骤1:标记GC Roots 能关联到的对象,速度很快,’
步骤2:并发标记阶段就是从 GC Roots 的直接关联对象的过程(耗时较长,但不需要停顿用户线程)
步骤3:重新标记,则是为了修正并发标记期间因用户程序运作而导致标记产生变动的那一部分标记记录。(比步骤1耗时长一点,但远比步骤2时间短)
步骤4:删除标记为已经死亡的对象
- 并发收集,低停顿
- CMS缺点
1:CMS收集器对处理器资源非常敏感:垃圾收集过程中直观感受就是线程速度变慢了(或者页面响应速度)但速度下降幅度没有那么明显
2:CMS处理器无法处理【浮动垃圾】
3:基于标记-清除算法,会产生空间碎片,解决方案,CMS回收若干次之后,进行碎片化整理,具体多少次由参数控制:-XX:CMSFULLGCSBefore-Compaction
Garbage First 收集器(G1)
- 不区分新生代和老年代
- 基于Region 的内存布局
- JDK8默认的垃圾收集器是 Parallel Scavenge(新生代)+ Serial Old(老年代),JDK9默认收集器是G1,且宣告CMS不推荐使用
- 1)初始标记 ;2)并发标记 3)最终标记 4)帅选回收
步骤1:标记GCRoot 能直接关联到的对象(stw)
步骤2:从GC Root 开始对中对象进行可达性分析,递归扫描整个堆里的对象图
步骤3:对用户线程做另一个短暂的暂停,用于处理并发阶段结束后遗留下来的最后那少量的SATB记录(stw)
步骤4:负责更新Region 的统计数据,对各个Region 的回收价值和成本进行排序,然后根据用户所期望的停顿时间来指定回收计划,可以自由任意选择多个Region构成回收集,然后回收那一部分。清理对应的region,将存活对象复制到空的Region (stw)
G1比CMS比较
1:G1可以指定最大停顿时间
2:CMS采用标记-清除 算法,G1 整体是标记-整理算法,从局部(Region)来看是标记-复制算法,意味着G1回收时候不会产生内存空间碎片。
3:G1垃圾回收器更占用内存和程序运行额外的负载。
具体哪款垃圾收集器要更好,往往针对具体的场景才能做定量比较的,小内存应用上CMS大概率会优于G1,大内存应用G1则大多数能发挥其优势。
衡量垃圾回收器指标
- 内存占用
- 吞吐量
- 延迟