jvm垃圾回收器
新生代收集器
- Serial:是一款用于新生代的单线程收集器,采用复制算法进行垃圾收集。不仅用一条线程执行垃圾收集工作,它在收集的同时,所有用户线程必须暂停。一般单核服务器使用,可以用-XX:+UserSerialGC来选择Serial作为新生代收集器。
- ParNew:是一个Serial多线程版本,ParNew在单核CPU环境中并不会比Serial收集器达到更好的效果,它默认开启的线程数和cpu数量一致。可以用-XX:+ParallelGCThreads来设置垃圾收集的线程数。新生代收集器默认就是ParNew,也可以使用 -XX:+UserParNewGC来指定。
- 一般在多核服务器,与CMS收集器搭配使用。-XX:+UserConcMarkSweepGC来选择CMS作为老年代收集器
- Parallel Scavenge:是一款用于新生代的多线程收集器,与ParNew不同之处是,ParNew是尽可能缩短垃圾收集时用户线程的停顿时间,Parallel Scavenge的目标是达到一个可控制的吞吐量。
吞吐量=运行代码时长/(运行代码时长 + 垃圾收集时长)
-XX:MaxGCPauseMillis来设置收集器尽可能在多长时间内完成内存回收
-XX:GCTimeRatio来精确控制吞吐量
jdk7 jdk8默认采用Parallel Scavenge作为新生代收集器
老年代收集器
- Serial Old:是Serial老年代版本,同样是一个单线程收集器,采用标记-整理算法。
- CMS:是一种以最短回收停顿时间为目标的收集器,用户线程最短停顿。
垃圾回收4个步骤
初始标记:标记一个GC Roots能直接关联的对象,速度较快。
并发标记:进行GC Roots 追踪,标记出全部的垃圾对象,耗时较长。
重新标记:修正并发标记阶段,引用用户程序继续运行而导致变化的对象的标记记录。
并发清除:用标记-清除算法清除垃圾对象,耗时较长。
CMS对CPU资源敏感,默认分配的垃圾收集线程数为(cpu数+3)/4,随着cpu数量下降,占用cpu资源越多,吞吐量越小。
无法清除浮动垃圾,在清理的过程中用户线程还在运行,不断的产生新的垃圾。CMS在运行过程中会预留内存空间,当预留内存空间无法满足用户线程的需要就会出现concurrent mode failure错误。这时就会重新采用Serial old来进行垃圾收集。
因为CMS是基于标记-清除算法,所以垃圾回收后会产生空间碎片,通过-XX:UserCMSCompactAtFullCollection开启碎片整理(默认开启),-XX:CMSFullGCsBeforeCompaction设置执行多少次不压缩,Full GC之后一次压缩。
-XX:+UserConMarkSweepGC来设置CMS作为老年代收集器。 - Parallel Old:是Parallel Scavenge老年代版本,是一个多线程收集器,采用标记-整理算法,可以与Parallel Scavenge收集器搭配,可以充分利用多核cpu计算能力。jdk7 jkd8默认采用此收集器。-XX:+UseParallelOldGC
堆内存垃圾收集器
- G1:是jdk1.7才正式引用的商用收集器,jdk9默认收集器,G1进行垃圾收集的范围是整个堆内存,将堆内存划分多个大小相等的独立区域,这个区域可能是eden,Survivor,老年代。最多可以设置2048个区域。
初始化标记:标记出GC Roots直接关联的对象,这个阶段速度比较快,需要停止用户线程,单线程执行。
并发标记:从GC Roots开始对堆中的对象进行可达新分析,找出存活对象,可以和用户线程并发执行。
最终标记:修正并发标记阶段引用户程序执行而产生变动的标记记录。
筛选回收:对各个区域的回收价值和成本进行排序,根据用户所期望的GC停顿时长,来决定回收计划。
-XX:+UseG1GC
JVM垃圾收集器
- -XX:+UseSerialGC:在新生代和老年代使用串行收集器。
- -XX:+UseParNewGC:在新生代使用并行收集器。
- -XX:+UseParallelGC:新生代使用并行回收收集器,关注吞吐量。
- -XX:+UseParallelOldGC:老年代使用并行回收收集器。
- -XX:+ParallelGCThreds:设置用于垃圾回收的线程数。
- -XX:+UseConcMarkSweepGC:新生代使用并行收集器,老年代使用CMS收集器+串行收集器。
- -XX:ParallelCMSThreads:设置CMS的线程数量。
- -XX:+UseG1GC:启动G1垃圾回收器。