Parallel Old
Parallel Scaevnge 老年代,标记-整理
JDK 6
配合 Parallel Scavenge
CMS收集器
关注回收停顿时间
互联网服务端主流
老年代
JDK5
标记-清除
步骤
初始标记
stw
标记gc roots 直接关联的对象
并发清除
缺点 1:cpu资源敏感
线程数=(核数+3)/4
核数少于4时对用户程序影响较大
资源少时用增量式并发收集器,i-cms改进,即抢占式并发,jdk7开始废弃
缺点2:无法处理“浮动垃圾”
并发过程中用户程序还在不停的生成垃圾
-XX: CMSInitiatingOccu-pancyFraction,控制触发cms回收的老年代内存使用百分比
太低,回收频率高
太高,容易 Concurrent mode failure,使用Serial Old 进行stw
缺点3:标记-清除 产生内存碎片,没有连续空间放大对象执行full gc
-XX: +UseCMS-CompactAtFullCollection,默认开启,full时整理碎片,jdk9 废弃
-XX: CMSFullGCsBeforeCompaction,默认0,JDK 9废弃,n次full gc后进行碎片整理
Garbage First 收集器
JDK 7 Update 4
JDK8 Update 40完成类卸载支持,完全完成
面向堆内任何区域回收,Mixed GC 模式,而非之前的单独面向某个分代
按分代设计,但内存区域按连续固定大小空间设置为一个Region
每个Region按需扮演Eden,Survivor,Old
Humongous Region:专门存放超过0.5Region的大对象,该区域被当成老年代处理
具体思路
维护一个优先级列表,记录每个Region的价值(回收时间,回收内存大小的经验值)
-xx:MaxGCPaulseMills 设定gc停顿时间,根据优先级列表评估要回收的Region,即最先回收价值最高的
关键问题
跨Region引用
记忆集-双向卡表
HashMap,Key是别的Region的起始地址, Value是一个集合, 里面存储的元素是卡表的索引号
需要更多的内存空间,堆的10%-20%
并发标记导致标记错误
原始快照算法进行修正
每个Region计了两个名为TAMS(Top at Mark Start) 的指针,将一部分区域作为新对象的分配空间,此空间上的对象都默认为存活
如果创建比回收快则stw进行full gc
如何实现可靠停顿时间预测模型
衰减均值理论基础,最近的统计结果能预测目前最真实的状态
每个Region的回收耗时、 每个Region记忆集里的脏卡数量等各个可测量的步骤花费的成本, 并分析得出平均值、 标准偏差、 置信度等统计信息
根据统计信息决策回收哪些Region
大致步骤
初始标记
标记一下GC Roots能直接关联到的对象
修改 TAMS指针,用于新对象分配
短暂停顿
并发标记
遍历整对象图,并记录并发时发生的对象引用删除
筛选回收
Region统计数据更新
复制回收该Region,即Region间的复制
必须停顿,复制使得对象移动
与cms的对比
1、记忆集实现更复制,每个Region都有,需要更多内存空间
2、还采用写前屏障保证实现最终标记的原始快照。需要更多的计算,因此采用队列进行异步处理
经验上:cms适用小内存应用,g1适用大内存,6-8g之间是两者平衡点,那么这个平衡点后g1比较有优势