JVM参数和监控工具介绍
这篇文章主要有三部分内容,第一部分是介绍一些常用的java虚拟机的参数设置,第二部分是一些常用的用于监控虚拟机的一些命令,第三部分主要介绍一下根据这些监控命令集成的可视化工具。
JVM参数
Jvm的参数主要分为三类,一类是标准参数,一类是-X参数,还有一类是 XX参数。
标准参数:标准参数中包括功能和输出的参数都是很稳定的,很可能在将来的 JVM 版本中不会改变,可以使用java命令检索出所有的标准参数。如-server 、 -version、-? -help等。
x参数:x参数在未来的JVM版本中可能发生改变,使用java -X命令可以查看x参数如下所示:
H:\IDEAworkSpace\springdemo>java -X
-Xmixed 混合模式执行 (默认)
-Xint 仅解释模式执行
-Xbootclasspath:<用 ; 分隔的目录和 zip/jar 文件>
设置搜索路径以引导类和资源
-Xbootclasspath/a:<用 ; 分隔的目录和 zip/jar 文件>
附加在引导类路径末尾
-Xbootclasspath/p:<用 ; 分隔的目录和 zip/jar 文件>
置于引导类路径之前
-Xdiag 显示附加诊断消息
-Xnoclassgc 禁用类垃圾收集
-Xincgc 启用增量垃圾收集
-Xloggc: 将 GC 状态记录在文件中 (带时间戳)
-Xbatch 禁用后台编译
-Xms 设置初始 Java 堆大小
-Xmx 设置最大 Java 堆大小
-Xss 设置 Java 线程堆栈大小
-Xprof 输出 cpu 配置文件数据
-Xfuture 启用最严格的检查, 预期将来的默认值
-Xrs 减少 Java/VM 对操作系统信号的使用 (请参阅文档)
-Xcheck:jni 对 JNI 函数执行其他检查
-Xshare:off 不尝试使用共享类数据
-Xshare:auto 在可能的情况下使用共享类数据 (默认)
-Xshare:on 要求使用共享类数据, 否则将失败。
-XshowSettings 显示所有设置并继续
-XshowSettings:all
显示所有设置并继续
-XshowSettings:vm 显示所有与 vm 相关的设置并继续
-XshowSettings:properties
显示所有属性设置并继续
-XshowSettings:locale
显示所有与区域设置相关的设置并继续
-X 选项是非标准选项, 如有更改, 恕不另行通知。
并且我们注意到结尾有一句话,-X 是非标准的参数,更改来的话是不会另行通知的。
** XX 参数:**
它们同样不是标准的,然而,在实际情况中 X 参数和 XX 参数并没有什么不同。X 参数的功能是十分稳定的,然而很多 XX 参数仍在实验当中(主要是 JVM 的开发者用于 debugging 和调优 JVM 自身的实现)。
-XX 参数是不稳定的参数,此类参数的设置很容易引起JVM 性能上的差异,使JVM存在极大的不稳定性。主要按以下规则分为三类:
- 布尔类型参数值:
-XX:+
表示启用该选项
-XX:-
表示关闭该选项 - 数字类型参数值:
-XX:
给选项设置一个数字类型值,可跟随单位,如 -XX:MetaspaceSize=10M - 字符串类型参数值:
-XX:
给选项设置一个字符串类型值,通常用于指定一个文件、路径或一系列命令列表。例如:-XX:HeapDumpPath=./dump.core
下面来介绍以下JVM调优方面常用的参数设置:
堆的内存设置参数:
参数 | 含义 | 说明 |
---|---|---|
–Xms=512M | 设置堆的初始化大小为512M | 可简写为 –Xms512M |
-Xmx=1024M | 设置堆的最大内存为1024M | 可简写为 -Xmx1024M |
–Xmn=300M | 设置堆的新生代的大小为300M | –Xmn300M ,Sun官方推荐配置为整个堆的3/8 |
–Xss512k | 设置堆栈大小为512k | JDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K. |
-XX:MetaspaceSize500M | 设置元数据区大小为500M | jdk1.8的元数据区 |
-XX:NewRatio=3 | 设置年轻代和老年代的分配比值大小 | 设置为3,则年轻代与年老代所占比值为1:3,年轻代占整个堆栈的1/4 |
-XX:SurvivorRatio=8 | 设置年轻代中Eden区与Survivor区的大小比值 | 设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。 |
-XX:NewSize=20M | 设置年轻代的大小 | 新生代,吞吐量优先 |
-XX:OldSize=50M | 设置老年代大小 | 老年代,吞吐量优先 |
-XX:+UseParallelGC | 使用UseParallelGC-XX:+UseParallelOldGC | |
-XX:+UseParallelOldGC | 使用UseParallelOldGC | |
-XX:+UseConcMarkSweepGC | 使用CMS | 老年代,停顿时间优先 |
-XX:+UseG1GC | 使用G1GC | 新生代,老年代,停顿时间优先 |
-XX:+HeapDumpOnOutOfMemoryError | 启动堆内存溢出打印 | 当JVM堆内存发生溢出时,也就是OOM,自动生成dump文件 |
-XX:HeapDumpPath=heap.hprof | 指定堆内存溢出打印目录 | 表示在当前目录生成一个heap.hprof文件 |
-XX:MaxTenuringThreshold=6 | 提升年老代的最大临界值 | 默认值为 15 |
-XX:G1HeapWastePercent | 允许的浪费堆空间的占比 | 默认是10%,如果并发标记可回收的空间小于10%,则不会触发MixedGC。 |
-XX:MaxGCPauseMillis=20-XX:ConcGCThreads=nms | G1最大停顿时间 | 暂停时间不能太小,太小的话就会导致出现G1跟不上垃圾产生的速度。最终退化成Full GC。所以对这个参数的调优是一个持续的过程,逐步调整到最佳状态。 |
-XX:ConcGCThreads=n | 并发垃圾收集器使用的线程数量 | 默认值随JVM运行的平台不同而不同 |
-XX:G1MixedGCLiveThresholdPercent=65 | 混合垃圾回收周期中要包括的旧区域设置占用率阈值 | 默认占用率为 65% |
-XX:G1OldCSetRegionThresholdPercent=1 | 描述Mixed GC时,Old Region被加入到CSet中 | 默认情况下,G1只把10%的Old Region加入到CSet中 |
XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStampsXloggc:$CATALINA_HOME/logs/gc.log | 打印出GC日志 |
常用的命令
jps
jps 命令类似与 linux 的 ps 命令,是一个显示当前所有java进程pid的命令。 通过 jps 命令可以方便地查看 Java 进程的启动类、传入参数和 Java 虚拟机参数等信息。
jps后面可以跟随多种命令:
-q:只输出进程 ID
-m:输出传入 main 方法的参数
-l:输出完全的包名,应用主类名,jar的完全路径名
-v:输出jvm参数
-V:输出通过flag文件传递到JVM中的参数
例如:
H:\IDEAworkSpace\springdemo>jps
13856 Jps
14848 Launcher
8656
19508 Bootstrap
jinfo 实时查看和调整JVM配置参数
jinfo 是 JDK 自带的命令,可以用来查看正在运行的 java 应用程序的扩展参数,包括Java System属性和JVM命令行参数;也可以动态的修改正在运行的 JVM 一些参数。
jinfo的用法:
H:\IDEAworkSpace\springdemo>jinfo
Usage:
jinfo [option]
(to connect to running process)
jinfo [option]
(to connect to a core file)
jinfo [option] [server_id@]
(to connect to remote debug server)
where
例如:```markdown
H:\IDEAworkSpace\springdemo>jinfo -flag MaxHeapSize 19508
-XX:MaxHeapSize=2071986176
```
jstat
Jstat是JDK自带的一个轻量级小工具,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。
jstat的用法:
H:\IDEAworkSpace\springdemo>jstat
invalid argument count
Usage: jstat -help|-options
jstat -
option: 参数选项
-t: 可以在打印的列加上Timestamp列,用于显示系统运行的时间
-h: 可以在周期性数据数据的时候,可以在指定输出多少行以后输出一次表头
vmid: Virtual Machine ID( 进程的 pid)
interval: 执行每次的间隔时间,单位为毫秒
count: 用于指定输出多少次记录,缺省则会一直打印
我们只需要输入命令如 jstat -options就能知道选项有哪些。
H:\IDEAworkSpace\springdemo>jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
如:查看垃圾收集信息,每秒打印一次,一共打印10次
C:\Users\Administrator>jstat -gc 19508 1000 10
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
21504.0 21504.0 0.0 0.0 199168.0 24266.2 72704.0 29918.3 21248.0 20697.8 2560.0 2291.5 11 0.124 1 0.097 0.221
jstack
jstack命令用来查看线程堆栈信息:
例如:
H:\IDEAworkSpace\springdemo>jps
8656
15396 Jps
19508 Bootstrap
19752 Launcher
H:\IDEAworkSpace\springdemo>jps
8656
18980 Launcher
18904 DeadLockDemo
13356 Jps
H:\IDEAworkSpace\springdemo>jstack 18904
2020-01-05 16:00:44
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.74-b02 mixed mode):
"DestroyJavaVM" #14 prio=5 os_prio=0 tid=0x0000000002f43800 nid=0x10a0 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
"Thread-1" #13 prio=5 os_prio=0 tid=0x000000001acff000 nid=0x4b74 waiting for monitor entry [0x000000001b4de000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threaddemo.DeadLockDemo.lambda$deadLock$1(DeadLockDemo.java:34)
- waiting to lock <0x00000000d6f996c0> (a java.lang.String)
- locked <0x00000000d6f996f0> (a java.lang.String)
at threaddemo.DeadLockDemo$$Lambda$2/1702297201.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
"Thread-0" #12 prio=5 os_prio=0 tid=0x000000001acfc000 nid=0x38b0 waiting for monitor entry [0x000000001b3df000]
java.lang.Thread.State: BLOCKED (on object monitor)
at threaddemo.DeadLockDemo.lambda$deadLock$0(DeadLockDemo.java:24)
- waiting to lock <0x00000000d6f996f0> (a java.lang.String)
- locked <0x00000000d6f996c0> (a java.lang.String)
at threaddemo.DeadLockDemo$$Lambda$1/2084435065.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
jmap
jmap是一个多功能的命令。它可以生成 java 程序的 dump 文件, 也可以查看堆内对象示例的统计信息、查看 ClassLoader 的信息以及 finalizer 队列。
例如:打印出堆内存相关信息:
H:\IDEAworkSpace\springdemo>jmap -heap 18904
Attaching to process ID 18904, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.74-b02
using thread-local object allocation.
Parallel GC with 8 thread(s)
Heap Configuration:
MinHeapFreeRatio = 0
MaxHeapFreeRatio = 100
MaxHeapSize = 2071986176 (1976.0MB)
NewSize = 42991616 (41.0MB)
MaxNewSize = 690487296 (658.5MB)
OldSize = 87031808 (83.0MB)
NewRatio = 2
SurvivorRatio = 8
MetaspaceSize = 21807104 (20.796875MB)
CompressedClassSpaceSize = 1073741824 (1024.0MB)
MaxMetaspaceSize = 17592186044415 MB
G1HeapRegionSize = 0 (0.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 32505856 (31.0MB)
used = 7808328 (7.446601867675781MB)
free = 24697528 (23.55339813232422MB)
24.02129634734123% used
From Space:
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
To Space:
capacity = 5242880 (5.0MB)
used = 0 (0.0MB)
free = 5242880 (5.0MB)
0.0% used
PS Old Generation
capacity = 87031808 (83.0MB)
used = 0 (0.0MB)
free = 87031808 (83.0MB)
0.0% used
3514 interned Strings occupying 286552 bytes.
dump出堆内存相关信息:
H:\IDEAworkSpace\springdemo>jmap -dump:format=b,file=G://heap.hprof 18904
Dumping heap to G:\heap.hprof ...
Heap dump file created
一般在开发中,JVM参数可以加上下面两句,这样内存溢出时,会自动dump出该文件
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heap.hprof
常用的分析工具
jconsole
JConsole工具是JDK自带的可视化监控工具。查看java应用程序的运行概况、监控堆信息、永久区使用
情况、类加载情况等,直接输入命令jconsole即可打开:
如图所示:
JConsole 基本包括以下基本功能:概述、内存、线程、类、VM概要、MBean。并且可以对线程进行死锁检测。
jvisualvm
它主要用来监控JVM的运行情况,可以用它来查看和浏览Heap Dump、Thread Dump、内存对象实例情况、GC执行情况、CPU消耗以及类的装载情况。
使用jvisualvm来监控需要安装插件:VisualVM,可以直接访问官网:https://visualvm.github.io/pluginscenters.html 下载对应的jdk版本安装即可。安装之后打开,选择一个java进程监控,如图:
jvisualvm工具使用起来要更直观一点,界面也很友好。可以看到它给我们检测到一个死锁,
并且可以直接查看线程dump。
并且 也可以直接添加dump文件进行分析。
Arthas
Arthas 是开源出来的一款 Java 诊断利器。主要是针对线上环境,Arthas采用命令行交互模式,同时提供丰富的 Tab 自动补全功能,进一步方便进行问题的定位和诊断。
这里我们使用官网推荐的arthas-boot
下载arthas-boot.jar,然后用java -jar的方式启动:
curl -O https://alibaba.github.io/arthas/arthas-boot.jar
java -jar arthas-boot.jar
如图所示,启动成功:
使用help命令查看具体每个命令的使用,
[arthas@8656]$ help
NAME DESCRIPTION
help Display Arthas Help
keymap Display all the available keymap for the specified connection.
sc Search all the classes loaded by JVM
sm Search the method of classes loaded by JVM
classloader Show classloader info
jad Decompile class
getstatic Show the static field of a class
monitor Monitor method execution statistics, e.g. total/success/failure count, average rt, fail rate, etc.
stack Display the stack trace for the specified class and method
thread Display thread info, thread stack
trace Trace the execution time of specified method invocation.
watch Display the input/output parameter, return object, and thrown exception of specified method invocation
tt Time Tunnel
jvm Display the target JVM information
ognl Execute ognl expression.
mc Memory compiler, compiles java files into bytecode and class files in memory.
redefine Redefine classes. @see Instrumentation#redefineClasses(ClassDefinition...)
dashboard Overview of target jvm's thread, memory, gc, vm, tomcat info.
dump Dump class byte array from JVM
heapdump Heap dump
options View and change various Arthas options
cls Clear the screen
reset Reset all the enhanced classes
version Display Arthas version
shutdown Shutdown Arthas server and exit the console
stop Stop/Shutdown Arthas server and exit the console. Alias for shutdown.
session Display current session information
sysprop Display, and change the system properties.
sysenv Display the system env.
vmoption Display, and update the vm diagnostic options.
logger Print logger info, and update the logger level
history Display command history
cat Concatenate and print files
pwd Return working directory name
mbean Display the mbean information
grep grep command for pipes.
profiler Async Profiler. https://github.com/jvm-profiling-tools/async-profiler
想要了解更过多Arthas的相关信息可以查看官网:https://github.com/alibaba/arthas
MAT
MAT(Memory Analyzer Tool)工具是eclipse的一个插件(可以单独使用),使用起来非常方便,尤其是在分析大内存的dump文件时,可以非常直观的看到各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系、利用OQL对象查询,以及可以很方便的找出对象GC Roots的相关信息,还能够快速为开发人员生成内存泄露报表,方便定位问题和分析问题。
MAT官网下载地址:https://www.eclipse.org/mat/downloads.php
下载好之后,打开工具,我这里找了一个OOM的的dump文件,使用MAT打开这个文件:
首先介绍下这个工具的常用选项:
视图 | 含义 |
---|---|
Histogram | Histogram可以列出内存中的对象,对象的个数及其大小 |
Dominator tree | 占用总内存的百分比来列举所有实例对象,可以在这里直观的看到哪些是大对象 |
Top Consumers | 该视图会显示可能的内存泄漏点 |
Leak Suspects | 通过MA自动分析泄漏的原因 |
Histogram
它按类名将所有的实例对象列出来,点击表头(Class Name)可以排序,第一行输入正则表达式可以过滤筛选 ;
- Class Name : 类名称,java类名
- Objects : 类的对象的数量,这个对象被创建了多少个
- Shallow Heap :一个对象内存的消耗大小,不包含对其他对象的引用
- Retained Heap :是shallow Heap的总和,也就是该对象被GC之后所能回收到内存的总和
快速找出某个实例没被释放的原因,可以右健 Path to GC Roots–>exclude all phantom/weak/soft etc. references
它展示了对象间的引用关系:
Dominator tree:
以占用总内存的百分比来列举所有实例对象,可以在这里直观的看到哪些是大对象:
Top Consumers:
这个维度展示了对象占用的内存分布:
可以查看每一个列表下面的分析:
Leak Suspects:
界面上非常直观的展示了一个饼图,该图深色区域被怀疑有内存泄漏,可以发现整个heap才15M内存,深色区域就占了92.48%。接下来是一个简短的描述,告诉我们main线程占用了大量内存,并且明确指出system class loader加载的“java.lang.Thread”实例有内存聚集,并建议用关键字“java.lang.Thread”进行检查。在下面还有一个“Details”链接,可以查看明细信息。
以上只是简单的介绍了下MAT工具的使用,具体或者更详细的使用可以查看官网,这里有很多关于MAT的使用经验及介绍。https://wiki.eclipse.org/MemoryAnalyzer/Learning_Material
本篇文章罗列了一些JVM内存相关的参数和一些获取JVM运行状况的一些参数以及线程Dump,堆Dump等分析工具,理解这些参数命令和熟悉工具的使用是我们读懂GC日志和对JVM进行调优的前提。