JVM基础
参数
启动相关
-client
client模式,启动速度比较快,但运行时性能和内存管理效率不高(客户端或测试)
-server
server模式,启动速度比较慢,但运行时性能和内存管理效率很高(生产,默认)
-classpath
加载jar包路径
内存相关
-Xms
堆最小内存,jvm初始化时申请
-Xmx
堆最大内存,超出报OOM
-Xmn
新生代内存,包括Eden区(80%)和两块Survior区(20%)
-XX:NewRatio
新生代与老年代内存占比(减去持久代)
-XX:SurvivorRatio
两块Survior区与Eden区比例,默认8,即2:8
-Xss
每个线程堆栈大小
-XX:PermSize
持久代内存
-XX:MaxPermSize
最大持久代内存
GC相关
+表示true,-表示false
Serial
-XX:+UseSerialGC
年轻代:Serial,老年代:Serial Old
-XX:+UseParNewGC
年轻代:ParNew,老年代:Serial Old
CMS
-XX:+UseConcMarkSweepGC
年轻代:ParNew,老年代:CMS
-XX:-CMSPrecleaningEnabled
不进行 preclean
-XX:CMSInitiatingOccupancyFraction
内存占用率达到多少启用GC
-XX:+UseCMSCompactAtFullCollection
开启FullGC后进行内存压缩
-XX:CMSFullGCsBeforeCompaction
多少次FullGC后进行内存压缩
-XX:+CMSClassUnloadingEnabled
允许对持久代中不再使用的class元数据进行回收
Parallel
-XX:+UseParallelGC
年轻代:Parallel Scavenge,老年代:Serial Old
-XX:+UseParallelOldGC
年轻代:Parallel Scavenge,老年代:Parallel Old
G1
-XX:+UseG1GC
年轻代:G1,老年代:G1
通用
-XX:ParallelGCThreads
并行线程数,建议与核心数一致
-XX:MaxGCPauseMillis
最大GC停顿时间
垃圾收集器
垃圾收集器图1中的 ParallelScavenge、Parallel Old 收集器代表的就是 throughput 收集器,现在主流的配置一般是:
- ParNew + CMS + Serial Old( 备用 )
- ParallelScavenge + Parallel Old( jdk6 )
- G1( jdk7 update 4 及以上)
- ZGC( jdk11 试验阶段)
新生代的GC算法一般都采用标记-复制算法,老年代一般核心算法都是标记-压缩算法
!!! jdk11 推出了ZGC收集器,现在看介绍牛逼得一批,后续补充说明
serial 收集器(串行)
单线程,简单,适合于单CPU、客户端级别,吞吐量小,GC时会stw,但是在单核机子或年轻代内存只有几十上百M的桌面应用上,因为少去了线程切换的开销,反而效率更高
串行收集器
ParNew 收集器(并行)
多线程模式的 serial 收集器,在多核情况下要比 serial 性能高,但在单核,甚至是双核某些情况下,还不如 serial 收集器。
CMS 收集器(并发,响应时间)
多线程,并发标记-清除+压缩,可以设置FullGC的触发内存占比,可以按需要开启多少次GC后进行内存压缩,压缩会增加暂停时间。适合响应时间要求高的场合,缺点是比较耗CPU,且由于是并发,会消耗部分堆内存,若内存在清理未完成时被占满,则无法进行GC,一般需要设置备用串行收集器 Serial Old
并发标记清除收集器
throughput 收集器(并行,吞吐量)
多线程,适合于吞吐量要求较高的场合,比较适合中等和大规模的应用程序,不适合响应时间要求高的程序,保证最长时延下的最大吞吐量
并行收集器
G1 收集器(并发,吞吐量,响应时间)
G1收集器是一种服务器式垃圾收集器,适用于具有大内存容量的多处理器机器。采用堆内存分区(region)的方式,同时在执行全堆操作(如全局标记)时,应用程序线程也同步执行,防止因为堆内对象过多导致stw,实现高吞吐量以及保证低时延
G1内存模型
jvm检测工具(具体说明待补全)
jstack
jstat
jmap
jconsole
mat
arthas
总结
- 一般来说,最大与初始内存设置成一样,可以避免 jvm 频繁申请内存,如-Xms和-Xmx,-XX:PermSize和-XX:MaxPermSize;
- 高吞吐量和低暂停时间是矛盾关系,需要根据具体业务进行设置,因为高吞吐量意味着尽可能不进行GC,GC时堆内对象过多,stw时间长,而低暂停时间则需要更为频繁的GC,这样一直保持着短时间的stw时间。当然现在的G1还有ZGC都避免了全堆扫描,使得其保证高吞吐量的同时也能最大限度兼顾更低的暂停时间
- 具体的垃圾收集器选择不仅仅要考虑使用场景,还需要考虑机器本身的性能,若内存容量低,对时延要求又不是那么高,选择并行收集器比CMS、G1都要好,因为并发收集器本身是要占堆内存的。若为单核机器,则要选择串行垃圾收集器
参考文献
- Oracle.Garbage-First Collector[EB/OL].https://.docs.oracle.com/javase/7/docs/technotes/guides/vm/G1.html,1993-2018
- Oracle.JDK 11 Release Notes[EB/OL].https://www.oracle.com/technetwork/java/javase/11-relnote-issues-5012449.html#NewFeature,1993-2018
- 梁钟霖.JVM Throughput和CMS垃圾回收器[EB/OL].https://www.liangzl.com/get-article-detail-13400.html,2018-08-17