①单线程收集器
②简单高效,额外内存消耗最小,没有线程交互开销
③适合客户端模式虚拟机
①单线程收集器
②适合客户端模式虚拟机,服务端下适合于Serial和ParNew配合,可用作CMS后备预案
①多线程并行收集
②能与CMS和Serial Old配合,是激活CMS后的默认新生代收集器
①关注吞吐量,适合后台运算分析任务
三参数调控吞吐量:
-XX:MaxGcPauseMillis Parallel Scavenge最大垃圾收集停顿时间 -XX:GcTimeRatio=N Parallel Scavenge直接设置吞吐量(垃圾收集时间占百分之1/1+N) -XX:UseAdaptiveSizePolicy 激活后不需要人工指定-xmn新生代大小、-XX:SurvivorRatio(eden与survivor比例)、-XX:PretenureSizeThreshold(晋升老年代大小),虚拟机自动调整
②可自适应调节
吞吐量优先组合
①最短停顿时间为目标,并发收集、低停顿
②运作过程:
1)初始标记:stw,标记GCRoots直接关联到的对象 2)并发标记 3)重新标记:stw,是并发标记阶段的增量更新 4)并发清除
③缺点:
1)并发阶段占用线程,导致应用程序变慢,降低总吞吐量 2)无法处理浮动垃圾,可能出现Concurrent Mode Failure导致stw的FULL gc,也因此必须预留空间供并发时程序试用 3)标记清除导致的空间碎片
①面向服务端应用,适合大内存应用
②实现停顿时间模型:指定长度为M毫秒的时间片段内,垃圾收集时间大概率不超过N毫秒
③Mixed GC,java堆划分为多个Region,特殊地,Humongous用来存储大对象(超过单个Region一半的对象)。维护优先级列表,根据停顿时间选择优先处理Region。
④细节问题:
1)如何解决跨Region引用对象? 采用特殊记忆集,每个Region维护自己的记忆集,记录“我指向谁”和“谁指向我” 2)并发标记阶段如何解决两者干扰? 对象消失问题解决采用原始快照SATB方式。 新对象内存分配问题试用两个TAMS指针,用于分配内存,两个指针指向区域内对象默认存活 3)如何建立停顿时间模型?记录之前的回收耗时、脏卡数量等统计信息,衡量衰减均值
⑤运作过程
1)初始标记:stw,标记GCRoots直接关联到的对象,修改TAMS指针值 2)并发标记 3)重新标记:stw,是并发标记阶段的原始快照 ※4)筛选回收:stw,选择Region回收,回收Region的存活对象复制到空Region
⑥缺点
1)卡表复杂,多,内存占用高 2)为了维护原始快照,用到写前屏障跟踪指针变化情况,写后屏障更新卡表(同CMS);要执行的屏障放到消息队列,执行负载高
①是G1的继承者,与G1的不同之处?
1)默认不使用分代 2)回收阶段可并发 3)放弃记忆集,使用链接矩阵指明Region之间的跨代引用
②运作过程(标记阶段与G1相同)(并发标记、并发回收、并发引用更新)
1)初始标记:stw,标记GCRoots直接关联到的对象,修改TAMS指针值 2)并发标记 3)重新标记:stw,是并发标记阶段的原始快照 4)并发清理: 清理无存活对象Region ※5)并发回收:复制存活对象到空Region,采用读屏障和转发指针解决并发问题,回收集大小决定时间 6)初始引用更新:短暂停顿,确保移动完成 并发引用更新:按照物理地址顺序线性搜索,旧值改为复制到的新值 最终引用更新:停顿,解决GC Roots的引用更新 7)并发清理
③转发指针和引用访问屏障 +CAS
对象头增加引用字段,不处于并发移动状态时引用指向对象自己,移动时指向新对象。只拦截引用类型读–解决了并发读问题
CAS保证并发时对象的访问正确性–解决并发写问题
①也算是G1继承者,对比Shenandoah不同之处?
1)Region分大中小,中小容量固定,大Region用于防大对象,不固定,不进行重分配 2)染色指针记录标记,Shenandoah和G1用bitmap记录打过标记的对象
②染色指针的优势?–标记直接打在指针高位
1)“自愈”特性使得某Region的存活对象被移走之后立即被释放重用,而She必须等待引用更新后才能清理 2)只使用读屏障,减少内存屏障数量 3)染色指针可扩展,用来记录更多数据
③运作过程
1)并发标记:类似G1、She,更新染色指针标志。 2)并发预备重分配:扫描所有Region统计得出重分配集。统计出的Region做标记复制,但是其他region也会发生垃圾收集。 *3)并发重分配:复制重分配集中存活对象,每个Region维护转发表。内存屏障截获访问请求,根据地址判断是否是重分配集中的,根据转发表访问并修改引用 4)并发重映射:修改重分配集中指向旧对象的引用,并不迫切,合并到下一次的并发标记去做