JVM内存模型
新生代 | 老年代 | JVM启动配置 |
Serial | Serial | -XX:+UseSerialGC |
Parallel Scavenge | Serial | -XX:+UseParallelGC -XX:-UseParallelOldGC |
Prallel New | Serial | -XX:+UseParNewGC |
Serial | Parallel Old | 不支持 |
Parallel Scavenge | Parallel Old | -XX:+UseParallelGC -XX:+UseParallelOldGC |
Prallel New | Parallel Old | 不支持 |
Serial | CMS | -XX:-UseParNewGC -XX:+UseConcMarkSweepGC |
Parallel Scavenge | CMS | 不支持 |
Prallel New | CMS | -XX:+UseParNewGC -XX:+UseConcMarkSweepGC |
G1 | -XX:+UseG1GC |
JDK1.8以及之前版本
JDK 1.8 默认是 Parallel Scavenge (新生代) + Paraller Old(老年代)
新生代收集器
Serial(复制算法)
简单高效,单线程,收集时暂停其他线程。
在单核场景下效率极高,建议使用场景:年轻代占用几十兆到一两百兆的应用。
使用方式:
-XX:+UseSerialGC。 一般是搭配老年代的Serial Old组合进行GC
ParNew(复制算法)
并行收集器,Serial的多线程版本,可配合老年代的CMS。
在多核情况下会比Serial要优秀,且随CPU数量增加优势会越来越明显,但不是成倍增长的(多线程切换开销)。
使用方式:
-XX:+UseParNewGC
-XX:ParallelGCThreads=N(建议N与CPU数一致)设置使用的线程数
ParNew是CMS收集器的默认年轻代收集器
Parallel Scavenge(复制算法)
以吞吐量为优先的多线程收集器,不支持CMS。
Parallel Scavenge收集器的特点是关注于吞吐量,即尽可能缩短垃圾收集时用户线程的停顿时间。
吞吐量 = 运行用户代码时间 /( 运行用户代码时间 + 垃圾收集时间 )
应用场景:
在后台运算,不需要产生很多交互的任务。
使用方式:
-XX:MaxGCPauseMillis:控制最大垃圾收集停顿时间,大于零的毫秒数。
-XX:GCTimeRatio:吞吐量大小,0到100的整数,垃圾收集时间占总时间的比例,计算1/(1+n)gc时间占用比例
-XX:UseAdaptiveSizePolicy:打开之后,就不需要设置新生代大小(-Xmn),Edian,survivor比例及(-XX:SurvivorRatio)晋升老年代年龄(-XX:PretenureSizeThreshold),虚拟机根据系统运行状况,调整停顿时间,吞吐量, GC自适应调节策略,区别parnew
老年代收集器
CMS--Concurrent Mark Sweep(标记清除算法)
CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:
初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent-mark) -> 重新标记(CMS-remark) -> 并发清除(CMS-concurrent-sweep) ->并发重设状态等待下次CMS的触发(CMS-concurrent-reset)。
其中的1,3两个步骤需要暂停所有的应用程序线程的。第一次暂停从root对象开始标记存活的对象,这个阶段称为初始标记;第二次暂停是在并发标记之后, 暂停所有应用程序线程,重新标记并发标记阶段遗漏的对象(在并发标记阶段结束后对象状态的更新导致)。第一次暂停会比较短,第二次暂停通常会比较长,并且 remark这个阶段可以并行标记。
而并发标记、并发清除、并发重设阶段的所谓并发,是指一个或者多个垃圾回收线程和应用程序线程并发地运行,垃圾回收线程不会暂停应用程序的执行,如果你有多于一个处理器,那么并发收集线程将与应用线程在不同的处理器上运行,显然,这样的开销就是会降低应用的吞吐量。Remark阶段的并行,是指暂停了所有应用程序后,启动一定数目的垃圾回收进程进行并行标记,此时的应用线程是暂停的。
CMS的young generation的回收采用的仍然是并行复制收集器,这个跟Paralle gc算法是一致的。
Serial Old(标记整理算法)
Serial的老年代版本。可作为CMS的后备预案
Parallel Old(标记整理算法)
Parallel Scavenge 的老年代版本,多线程吞吐量优先。