常用的性能调优命令

Sun JDK监控和故障处理命令有jps jstat jmap jhat jstack jinfo

jps

JVM Process Status Tool,显示指定系统内所有的HotSpot虚拟机进程。

参数:

​ - q : 只输出LVMID,省略主类的名称

​ - m:输出启动时传递给主类main的参数

​ - l:输出主类全名,如果是jar包,则输出jar路径

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

1
2
3
4
5
C:\Users\liwenbo\IdeaProjects\untitled\out>jps
4848 Launcher
6424 JvmTest7
6728
10476 Jps

jstat

jstat(JVM Statistics Monitoring Tool)是用于监视虚拟机各种运行状态信息的命令行工具。它可以显示本地或者远程虚拟机进程中的类加载、内存、垃圾收集、即时编译等运行时数据,在没有GUI图形界面、只提供了纯文本控制台环境的服务器上,它将是运行期定位虚拟机性能问题的常用工具。

jstat的主要选项如下:

image-20210809144356042

下面是一个执行jstat命令的例子:

image-20210809145144304

其中-gcutil是统计的选项,6424是通过jps查询到的VMID,3000和100是可选参数,表示每隔3000毫秒统计一次,一共统计100次。

jmap

jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文件)。如果不使用jmap命令,要想获取Java堆转储快照也还有一些比较“暴力”的手段:譬如在第2章中用过的-XX:+HeapDumpOnOutOfMemoryError参数,可以让虚拟机在内存溢出异常出现之后自动生成堆转储快照文件,通过-XX:+HeapDumpOnCtrlBreak参数则可以使用[Ctrl]+[Break]键让虚拟机生成堆转储快照文件,又或者在Linux系统下通过Kill-3命令发送进程退出信号“恐吓”一下虚拟机,也能顺利拿到堆转储快照。

jmap的作用并不仅仅是为了获取堆转储快照,它还可以查询finalize执行队列、Java堆和方法区的详细信息,如空间使用率、当前用的是哪种收集器等。

jmap的参数如下:

image-20210809150014256

下面是jmap执行的一个示例

1
2
3
D:\>jmap -dump:format=b,file=dump.bin 6424
Dumping heap to D:\dump.bin ...
Heap dump file created

输出的文件,可以使用JvisualVM打开。

jinfo

jinfo(Configuration Info for Java)的作用是实时查看和调整虚拟机各项参数。

image-20210809150616843

jhat

JDK提供jhat(JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照。jhat内置了一个微型的HTTP/Web服务器,生成堆转储快照的分析结果后,可以在浏览器中查看。不过实事求是地说,在实际工作中,除非手上真的没有别的工具可用,否则多数人是不会直接使用jhat命令来分析堆转储快照文件的,主要原因有两个方面。一是一般不会在部署应用程序的服务器上直接分析堆转储快照,即使可以这样做,也会尽量将堆转储快照文件复制到其他机器上进行分析,因为分析工作是一个耗时而且极为耗费硬件资源的过程,既然都要在其他机器上进行,就没有必要再受命令行工具的限制了。

jstack

jstack(Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。

jstack的可用选项如下:

image-20210809151345281

下面是一个jstack的执行示例:

image-20210809151622878

一般会将jstack的结果重定向到文本文件,然后分析文本文件的内容。

监控工具

JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是 jconsole 和 jvisualvm 这两款视图监控工具。

jconsole

用于对 JVM 中的内存、线程和类等进行监控;

image-20210808232811266

jvisualvm

JDK 自带的全能分析工具,可以分析:内存快照、线程快照、程序死锁、监控内存的变化、gc变化等。

image-20210808233101967

jmc

jdk7之前jmc是放在jdk下载的包中,jdk8之后需要单独下载。可以从下面的地址进行下载:

JDK Mission Control (JMC) 8 Downloads (oracle.com)

image-20210809133907388

常用的 JVM 调优的参数

堆内存相关

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
设置堆初始值
指令1:-Xms2g
指令2:-XX:InitialHeapSize=2048m
 
设置堆区最大值
指令1:`-Xmx2g` 
指令2: -XX:MaxHeapSize=2048m
 
缩小堆内存的时机
-XX:MaxHeapFreeRatio=70			//堆内存使用率大于70时扩张堆内存,xms=xmx时该参数无效,默认值70
 
扩张堆内存的时机
-XX:MinHeapFreeRatio=40			//堆内存使用率小于40时缩减堆内存,xms=xmx时该参数无效,默认值40
 
新生代内存配置
指令1:-Xmn512m
指令2:-XX:MaxNewSize=512m
 
2个survivor区和Eden区大小比率
指令:-XX:SurvivorRatio=6  	  //S区和Eden区占新生代比率为1:6,两个S区2:6
 
新生代和老年代的占比
-XX:NewRatio=4  			   	//表示新生代:老年代 = 1:4 即老年代占整个堆的4/5;默认值=2

方法区

1
2
3
4
5
初始化的Metaspace大小,
-XX:MetaspaceSize :
 
Metaspace最大值
-XX:MaxMetaspaceSize

线程栈内存

1
2
3
每个线程栈最大值
指令1:-Xss256k
指令2:-XX:ThreadStackSize=256k

注意: 栈设置太大,会导致线程创建减少。栈设置小,会导致深入不够,深度的递归会导致栈溢出。建议栈深度设置在3000-5000

配置垃圾收集器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Serial垃圾收集器(新生代)
开启:-XX:+UseSerialGC
关闭:-XX:-UseSerialGC
//新生代使用Serial  老年代则使用SerialOld
 
ParNew垃圾收集器(新生代)
开启 -XX:+UseParNewGC
关闭 -XX:-UseParNewGC
//新生代使用功能ParNew 老年代则使用功能CMS
 
Parallel Scavenge收集器(新生代)
开启 -XX:+UseParallelOldGC
关闭 -XX:-UseParallelOldGC
//新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器
 
ParallelOl垃圾收集器(老年代)
开启 -XX:+UseParallelGC
关闭 -XX:-UseParallelGC
//新生代使用功能Parallel Scavenge 老年代将会使用Parallel Old收集器
 
CMS垃圾收集器(老年代)
开启 -XX:+UseConcMarkSweepGC
关闭 -XX:-UseConcMarkSweepGC
 
G1垃圾收集器
开启 -XX:+UseG1GC
关闭 -XX:-UseG1GC