ParNew
ParNew就是Parallel New的意思,ParNew和Parallel Scavenge基本没什么区别,都是年轻代的垃圾回收器,就是在Parallel Scavenge的基础上做了一些简单的增强使其能够较好的配合CMS的使用,ParNew是Parallel Scavenge的一个变种
ParNew响应时间优先,Parallel Scavenge吞吐量优先
使用ParNew:-XX:+UseParNewGC
CMS
CMS全称Concurrent Mark Sweep,老年代的垃圾回收器,从名字可以看出它的垃圾回收线程可以与业务工作线程并发去执行,并且使用的垃圾回收算法是标记-清除算法。
使用CMS:-XX:+UseConcMarkSweepGC
CMS主要的四个阶段
- 第一个阶段:Initial Mark(初始标记阶段),CMS会找到"根"上的对象进行标记,不会标记非"根"的对象,此阶段会有STW,标记线程和业务线程不会并发执行
- 第二个阶段:Concurrent Mark(并发标记阶段),业务线程一边工作产生垃圾,回收线程一边标记垃圾,由于标记垃圾是GC最耗时的过程,所以CMS让回收线程个业务线程并发执行,业务线程虽然会慢一点但还是一直在执行的
- 第三个阶段:Remark(重新标记阶段),在第二阶段可能业务线程会产生新的垃圾,此阶段会把这些垃圾重新标记一下,会有STW,但第二阶段产生的垃圾不会很多因此业务线程停顿的时间不会很长
- 第四个阶段:Concurrent Sweep(并发清理阶段),业务线程边工作,垃圾回收线程边清理垃圾,这时业务线程会产生新的垃圾,这些垃圾会在下次GC的时候进行清理,这些垃圾被叫做浮动垃圾
CMS的问题
CMS有两大致命的问题,内存碎片化和浮动垃圾。
内存碎片化:CMS使用的是标记-清除算法,所以内存碎片化成了它天然的问题
浮动垃圾:第四阶段产生的垃圾
如果内存碎片化严重或浮动垃圾比较多,需要从年轻代进入老年代的这些对象已经找不到空间了,这时CMS会让单线程的垃圾回收器Serial
Old使用标记-压缩算法进行工作,这会导致STW的耗时特别特别的长
CMS问题的解决方案
方案一:降低触发CMS的阈值
JVM参数:-XX:CMSInitiatingOccupancyFraction 92%
方案二:增加内存,保证老年代有足够的空间
最小堆内存64M:-Xms64m
最大堆内存128M:-Xmx128m
设置年轻代大小128M:-Xmn128m
年轻代初始化大小为30M:-XX:NewSize=30m
年轻代最大大小为40M:-XX:MaxNewSize=40m
设置老年代/年轻代的比例:-XX:NewRatio=2