JVM调优入门

JVM调优入门

0、序

jdk1.8,hotspot虚拟机

官方参数文档链接

JDK8官方参数文档连接

JDK7官方参数文档连接

1、参数设置

所有配置参数笔者默认为大小写敏感,在使用时一定校验是否有符号、拼写、大小写错误

1.1 参数分类

  • 标准参数(-):所有的JVM实现都必须实现这些参数的功能,而且向上兼容;

  • 非标准参数(-X):默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向上兼容;

  • 非Stable参数(-XX):此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用(但是,这些参数往往是非常有用的);

1.2 标准参数

在控制台输入java 获取支持的标准参数

1.2.1 -client

设置jvm使用client模式,启动速度快,但运行时性能和内存管理效率不高,通常用于客户端应用程序或者PC应用开发和调试。

1.2.2 -server

设置jvm使server模式,启动速度比较慢,运行时性能和内存管理效率很高,适用于生产环境。在具有64位能力的jdk环境下将默认启用该模式。

1.2.3 -verbose

  • -verbose:class 输出jvm载入类的相关信息,当jvm报告说找不到类或者类冲突时可此进 行诊断。

  • -verbose:gc 输出每次GC的相关情况,后面会有更详细的介绍。

  • -verbose:jni 输出native方法调用的相关情况,一般用于诊断jni调用错误信息。

1.2.4 -D<名称>=<值>

设置系统属性运行在此jvm之上的应用程序可用System.getProperty("property")得到value的值。如果value中有空格,则需要用双引号将该值括起来。 如:-Dname="space string" 该参数通常用于设置系统级全局变量值,如配置文件路径,以便该属性在程序中任何地方都可访问。

1.2.5 -X

在控制台输入,输出非标准的参数列表及其描述。

java -X

1.3 非标准参数

非标准参数,是在标准参数的基础上进行扩展的参数,不同类型JVM上参数也有所不同。图仅作示例,全部非标准参数内容请自行查阅。

 

 

 

1.3.1 -Xmx

JVM最大允许分配的堆内存;默认为物理内存的1/4或者1G,最小为2M;可以指定单位,比如k、m,若不指定,则默认为字节。

-Xmx1024m //  == -Xmx1g,最大堆内存为1g

1.3.2 -Xms

JVM初始分配的堆内存,默认为物理内存的1/64,最小为1M;单位与-Xms一致,一般和Xmx配置成一样以避免每次gc后JVM重新分配内存;

1.3.3 -Xmn

年轻代内存大小(Eden+S0+S1)

1.3.4 -Xss

设置每个线程的栈大小,一般为512k/1M;

1.3.5 -Xloggc:file

与-verbose:gc功能类似,只是将每次GC事件的相关情况记录到一个文件中,文件的位置最好在本地,以避免网络的潜在问题。若与verbose命令同时出现,以-Xloggc为准。

-Xloggc:$CATALINA_BASE/logs/gc.log

1.4 非Stable参数

以-XX作为前缀的非Stable参数列表在JVM中可能是不健壮的,后续可能会在没有通知的情况下就直接取消了,但这些参数中的确有很多是对我们很有用的。

使用如下命令可以将支持的非Stable参数导出至文本:

java -XX:+PrintFlagsFinal > -XXCommandText.txt

在Hotspot中主要的参数可以大致分为3类:

  • 性能参数( Performance Options):用于JVM的性能调优和内存分配控制,如初始化内存大小的设置;

  • 行为参数(Behavioral Options):用于改变JVM的基础行为,如GC的方式和算法的选择;

  • 调试参数(Debugging Options):用于监控、打印、输出等jvm参数,用于显示jvm更加详细的信息;

使用方法有4种:

  • -XX: + <option> 启用选项

  • -XX: - <option> 不启用选项

  • -XX:<option>=<number> 给选项设置一个数字类型值,可跟单位

    如:-XX:NewSize=512M

  • -XX:<option>=<string> 给选项设置一个字符串值

    如:-XX:HeapDumpPath=./dump.core

1.4.1 性能参数

  • -XX:NewRatio=4:设置年轻代与年老代的比值为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5,常用值为[2](默认值)、3、4

  • -XX:SurvivorRatio=4:设置年轻代中Eden区与Survivor区的比值为4,则S0+S1:Eden 的比值为1+1 : 4,一个Survivor区占整个年轻代的1/6,常用值4、[8]

  • -XX:MetaspaceSize=256m、-XX:MaxMetaspaceSize=256M :设置元空间默认大小、最大值(jdk1.7方法区、持久代 -XX:MaxPermSize=16M)

  • -XX:MaxTenuringThreshold= 0:设置分代年龄,默认为15,如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。

  • -XX:ParallelGCThreads=8:并发垃圾收集时开启线程数量

  • -XX:ConcGCThreads=0:并行垃圾收集时开启的线程数量

1.4.2 行为参数

  • -XX:-DisableExplicitGC:禁止调用System.gc();但jvm的gc仍然有效

  • -XX:+ScavengeBeforeFullGC:Minor GC优先于Full GC执行

  • -XX:+UseConcMarkSweepGC :ParNewGC + CMS GC

    若出现Concurrent Mode Failure则使用 SerialOld GC替换CMS

  • -XX:+CMSParallelRemarkEnabled:搭配CMS使用,降低标记停顿

  • -XX:+UseSerialGC:Client模式下默认组合

    SerialGC + SerialOld GC 组合

  • -XX:+UseParNewGC:ParNewGC + SerialOld GC 组合

  • -XX:+UseParallelGC:Server模式下默认组合

    Parallel Scavenge GC + SerialOld GC 组合

  • -XX:+UseParallelOldGC:Parallel Scavenge GC + ParallelOldGC 组合

  • -XX:LargePageSizeInBytes=128M:内存页的大小

参考文献:《深入理解JAVA虚拟机》

1.4.3 调试参数

以下命令须配合-verbose:gc一起使用

  • -XX:+PrintGCDetails:打印GC详情

  • -XX:+PrintGCTimeStamps:打印发生fullgc的时间戳

  • -XX:-HeapDumpOnOutOfMemoryError:当首次遭遇OOM时导出此时堆中相关信息

  • -XX:+PrintGCApplicationStoppedTime:打印GC时SWT的时间

  • -XX:PrintHeapAtGC: 打印GC前后详细的堆栈信息

2、收集器套餐推荐

  • 一般来说,Java桌面应用,建议采用-client模式套餐即Serial+Serial Old收集器组合:-XX:+UseSerialGC

  • 在开发/测试环境,可以采用-server下默认参数即

    Parallel Scavenge + Serial Old收集器组合:-XX:+UseParallelGC

  • 在线上运算优先的环境,建议采用Parallel Scavenge+Serial Old收集器组合:-XX:+UseParallelGC

  • 在线上服务响应优先的环境,建议采用ParNew+CMS+Serial Old收集器组合:-XX:+UseConcMarkSweepGC

3、内存分配

  • 堆大小设置Xms 和 Xmx设置为老年代存活对象所占内存的3-4倍,即FullGC之后的老年代内存占用的3-4倍

  • 永久代 PermSize和MaxPermSize元空间Metaspacesize及MaxMetaspacesize设置为老年代存活对象的1.2-1.5倍。

  • 年轻代Xmn的设置为老年代存活对象的1-1.5倍。

  • 老年代的内存大小设置为老年代存活对象的2-3倍。

如:当系统稳定运行一段时间后,老年代所占内存为64M则有如下性能参数设置:

-Xms256M
-Xmx256M
-Xmn86M
-XX:MetaspaceSize=96M 
-XX:MaxMetaspaceSize=96M 
//年轻代:老年代 = 1:2

4、监控工具

4.1 命令行工具

4.1.1 jps命令

jps命令用于查询正在运行的JVM进程,命令格式为:

jps [option] [hostid]

常用的参数为:

  • -q:只输出VM ID,省略主类的名称

  • -m:输出虚拟机进程启动时传给主类main()函数的参数

  • -l:输出主类的全类名,如果进程执行的是Jar包,输出Jar路径

  • -v:输出虚拟机进程启动时JVM参数

4.1.2 jstat命令

jstat(Java Virtual Machine statistics monitoring tool)JDK自带的一个轻量级工具, 利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。

jstat有如下选项:

  • -class:监视类装载、卸载数量、总空间及类装载所耗费的时间

  • -gc:监听Java堆状况,包括Eden区、两个Survivor区、老年代、永久代等的容量,以用空间、GC时间合计等信息

  • -gccapacity:监视内容与-gc基本相同,但输出主要关注java堆各个区域使用到的最大和最小空间

  • -gcutil:监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比

  • -gccause:与-gcutil功能一样,但是会额外输出导致上一次GC产生的原因

  • -gcnew:监视新生代GC状况

  • -gcnewcapacity:监视内同与-gcnew基本相同,输出主要关注使用到的最大和最小空间

  • -gcold:监视老年代GC情况

  • -gcoldcapacity:监视内同与-gcold基本相同,输出主要关注使用到的最大和最小空间

  • -gcpermcapacity:输出永久代使用到最大和最小空间

  • -compiler:输出JIT编译器编译过的方法、耗时等信息

  • -printcompilation:输出已经被JIT编译的方法

示例:

监控GC情况,被监控VMID为12636,每1000ms收集一次GC状态,共收集5次

 

  • S0C:S0区容量(S1区相同,略)

  • S0U:S0区已使用

  • EC:E区容量

  • EU:E区已使用

  • OC:老年代容量

  • OU:老年代已使用

  • MC:MetaSpace容量

  • MU:MetaSpace区已使用

  • CCSC:当前压缩类空间大小

  • CCSU:当前压缩类空间已使用大小

  • YGC:Young GC(Minor GC)次数

  • YGCT:Young GC总耗时

  • FGC:Full GC次数

  • FGCT:Full GC总耗时

  • GCT:GC总耗时

4.2 图形化工具

4.2.1 JVisualVM

VisualVM是一个集成多个JDK命令行工具的可视化工具,它具备了插件扩展功能的特性,通过插件的扩展,可用于显示虚拟机进程及进程的配置和环境信息(jps,jinfo),监视应用程序的CPU、GC、堆、方法区及线程的信息(jstat、jstack)等。

JVisualVM插件下载链接

  • 使用方法:控制台键入 jvisualvm打开工具

  • 插件安装:下载对应jdk版本的visual gc插件,点工具-插件-已下载-打开安装。

  • 启用监控:右键点击本地VM进程-打开-Visual GC 观察JVM内存运行情况

5、调优论述

5.1 目的

  • 将转移到老年代的对象数量降低到最小;

  • 减少full GC的执行时间 — 减少业务阻塞;

5.2 原则

  • 多数的Java应用不需要在服务器上进行GC优化;

  • 多数导致GC问题的Java应用,都不是因为我们参数设置错误,而是代码问题;

  • 在应用上线之前,先考虑将机器的JVM参数设置到最优(最适合);

  • 减少创建对象的数量;

  • 减少使用全局变量和大对象;

  • GC优化是到最后不得已才采用的手段;

  • 在实际使用中,分析GC情况优化代码比优化GC参数要多得多;

5.3 调优方法

  • 方法1:稳定运行系统一段时间,使用监控工具查看当前JVM内存性能及gc情况,按照老年代占用内存比例,调整各内存性能参数。适合并发低、业务稳定应用。

  • 方法2:分析估算单业务线完整生命周期占用的内存(主要是新生代)情况,并结合当前服务器可以稳定处理的峰值并发量,合理分配新生代内存容量及配比。适合业务处理时间短,高并发的应用。

  • 方法3:选择适合的垃圾收集器套餐,系统默认参数足够应对绝大多数应用场景。

5.4 示例

仅供参考,先测后用

-Xmx300m                //最大堆大小             
-Xms300m                //最小堆大小
-Xmn100m                //新生代大小                      
-XX:SurvivorRatio=8     //Eden:Survivor
-XX:+UseConcMarkSweepGC //使用ParNew+CMS+Serial Old收集器组合
-XX:MaxTenuringThreshold=15 //分代年龄,15岁以后进入老年代
-XX:ParallelGCThreads=8 //CMS并行线程数
-XX:ConcGCThreads=8     //ParNew并发线程数
-XX:+DisableExplicitGC  //禁用System.gc()
-XX:+HeapDumpOnOutOfMemoryError //导出堆OOM的异常信息
-XX:HeapDumpPath=d:/a.dump      //导出路径        
-XX:+PrintGCDetails             //打印GC详情        
-XX:+PrintGCTimeStamps          //打印时间戳
-XX:+PrintHeapAtGC              //打印GC前后堆的情况
-XX:+TraceClassLoading          //显示类加载信息    

Surprise

当你在一家中小型公司,可能根本用不上JVM调优的相关内容,但这并不影响面试的时候被问,这就很无奈~多掌握一些总没什么错,99.9%的bug都是代码写的有问题,切勿让JVM背锅—至向上的自己...JVM入门,完结撒花~

猜你喜欢

转载自www.cnblogs.com/lijizhi/p/12434707.html