垃圾回收(四)垃圾回收器2
七种经典垃圾回收器
新生代回收器:Serial、ParNew、Parallel Scavenge;
老年代回收器:Serial Old、Parallel Old、CMS;
整堆回收器:G1;
Serial Old回收器:老年代、标记-压缩算法、串行回收、STW机制
ParNew回收器:新生代、复制算法、并行回收、STW机制
Parallel Scavenge(Parallel)回收器:新生代、复制算法、吞吐量优先、并行回收、STW机制
Parallel Old回收器:老年代、标记-压缩算法、并行回收、STW机制
-XX:+UserParallelGC 手动设置年轻代使用Parallel并行收集器;
-XX:+UserParallelOldGC 手动设置老年代使用Parallel Old并行收集器,与Parallel互相激活;
-XX:ParallelGCThreads 设置年轻代并发收集器的线程数,一般与CPU数量相同。当CPU数量小于8个,ParallelGCThreads的值默认等于CPU的数量,否则,ParallelGCThreads的值默认等于3+[5*CPU_Count]/8;
-XX:UseAdaptiveSizePolicy 设置Parallel具有自适应调节策略。在这种模式下,会自动的设置年轻代的大小、Eden和Survivor的比例、晋升老年代的年龄,已达到在堆大小、吞吐量和停顿时间之间的平衡点。
CMS回收器(Concurrent-Mark-Sweep):低延迟(强交互),并发回收(垃圾回收线程与用户程序线程同时工作)、标记-清除算法、STW机制
初始标记(Initial-Mark)阶段:在这个阶段,暂停所有工作进程,主要任务仅仅只是标记出GC Roots能直接关联到的对象。一旦标记完成之后就会恢复之前被暂停的所有应用线程,由于直接关联对象比较少,所以这里的速度非常快。
并发标记(Concurrent-Mark)阶段:从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时长但是不需要停顿用户线程。
重新标记(Remark)阶段:由于在并发标记阶段,程序的工作线程会和垃圾收集线程同时运行或交叉运行,因此为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那部分对象(标记阶段不确定是否为垃圾的对象)的标记记录,运行时间远比并发标记阶段的时间短。
并发清除(Concurrent-Sweep)阶段:清理删除掉标记阶段判断的已经死亡的对象,释放内存空间。由于不需要移动存活对象,所以这个阶段也是与用户线程并发。
产生内存碎片,埋下一颗定时炸弹;
对CPU资源非常敏感:虽然不会导致用户线程停顿,但会占用CPU资源,导致应用程序执行变慢,降低吞吐量;
无法处理浮动垃圾:在并发标记阶段如果产生新的垃圾对象,CMS将无法对这些垃圾对象进行标记,最终会导致这些新产生的垃圾对象没有及时回收;
-XX:UseConcMarkSweepGC 手动指定使用CMS,开启该参数后,会自动将-XX:UseParNewGC打开,即:ParNew(年轻代)+CMS(老年代)+Serial Old(替补);
-XX:CMSInitiatingOccupanyFraction 设置堆内存使用率的阈值,一旦达到阈值,便开始回收。jdk 5及以前默认为68%,jdk 6及以上默认为92%,如果内存增长缓慢,可以设置一个稍大的值,目的是为了有效的降低Full GC的次数;
-XX:UseCMSCompactAtFullCollection 用于指定在执行完Full GC后对内存进行压缩整理;
-XX:CMSFullGCsBeforeCompaction 设置在执行多少次Full GC后对内存空间进行压缩整理;
-XX:ParallelCMSThreads 设置CMS线程数量,默认启动的线程数为(ParallelGCThreads+3)/4,ParallelGCThreads是年轻代并行收集器的线程数;
以上总结
如果你想要最小化的使用内存和并行开销,请选Serial GC;
如果你想要最大化的应用程序吞吐量,请选Parallel GC;
如果你想要最小化GC的中断或停顿时间,请选CMS GC;
补(个人见解):