在jdk的开发包里,除了我们常用的java.exe
和javac.exe
程序外,还有一系列辅助工具,这些工具可以帮助我们更好地分析指定java程序的运行状态,比如jstack.exe
、jps.exe
、jstate.exe
等。下面我们对一些重要的工具进行讲解。
注意:在jdk8及以前,工具类的可执行文件的实现都在
lib/tools.jar
上,但是在jdk9及以后,以前存储在lib中的lib/rt.jar
、lib/tools.jar
、lib.dt.jar
,以及其他各种内部jar文件现在以更高效的格式存储在lib目录中特定的实现文件中。
注意:我使用的环境为Windows10,jdk11。此处放出jdk11工具程序的官方说明文档,读者可以从此文档中获取详细信息。
jps
命令会列出运行在本地的所有java进程。
它的相关参数如下:
-q
:指定jps只输出进程ID,而不输出类的名称。-m
:输出传递给java进程的参数。-l
:输出主函数的完整路径。-v
:显示传递给java虚拟机的参数。示例如下:
C:\Users\hu'nan>jps -m -l -v
19536 cn.bigkai.ApplicationStart -Xlog:gc=trace:file=gc.log -Xmx32M -Xms32M -javaagent:F:\instrument\java\idea2019\lib\idea_rt.jar=57122:F:\instrument\java\idea2019\bin -Dfile.encoding=UTF-8
jstat可以查看java虚拟机的运行时的相关信息 以及堆信息的详细情况。基本语法如下:
C:\Users\hu'nan>jstat --help
Usage: jstat --help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
jstat的相关参数如下:
option
的相关参数如下:
-t
参数可以在输出信息前加一个Timestamp列,显示程序的运行时间。-h
参数可以指定在周期性数据输出时,输出多少行数据后输出一个表头信息。interval
:指定输出统计数据的周期,单位为毫秒。count
:指定一个输出多少次数据。示例如下:
C:\Users\hu'nan>jstat -gcnew -t -h 2 19536 1000 6
Timestamp S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
2704.3 0.0 2048.0 0.0 2048.0 15 15 1024.0 12288.0 4096.0 1 0.004
2705.3 0.0 2048.0 0.0 2048.0 15 15 1024.0 12288.0 4096.0 1 0.004
Timestamp S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
2706.3 0.0 2048.0 0.0 2048.0 15 15 1024.0 12288.0 4096.0 1 0.004
2707.3 0.0 2048.0 0.0 2048.0 15 15 1024.0 12288.0 4096.0 1 0.004
Timestamp S0C S1C S0U S1U TT MTT DSS EC EU YGC YGCT
2708.3 0.0 2048.0 0.0 2048.0 15 15 1024.0 12288.0 4096.0 1 0.004
2709.3 0.0 2048.0 0.0 2048.0 15 15 1024.0 12288.0 4096.0 1 0.004
不同option
参数的输出信息不同,具体的可以自行百度了解。
前面我们讲了jps,了解到它的-v
参数会显示传递给虚拟机的参数,这次介绍的jinfo
命令更加强大,它不仅能查看虚拟机参数,而且可以在运行时修改部分参数。它的基本语法为:
C:\Users\hu'nan>jinfo --help
Usage:
jinfo <option> <pid>
(to connect to a running process)
jinfo相关参数如下:
option
的相关参数如下:
-flag
:打印java虚拟机指定参数的值。-flag[+-]
:设置指定Java虚拟机参数的布尔值。-flag=
:设置指定java虚拟机参数的值。注意:不是所有的参数都支持使用jinfo查看,也不是所有的参数都支持动态修改。可以通过命令行或者代码获取支持动态修改的JVM参数:
通过命令行获取:
Linux环境下:
java -XX:+PrintFlagsInitial | grep manageable
Window环境下:
通过API获取:
HotSpotDiagnosticMXBean.getDiagnosticOptions()
方法返回虚拟机支持动态修改的参数。public class DiagnosticOptionsTest { public static void main(String[] args) { HotSpotDiagnostic mxBean = new HotSpotDiagnostic(); List<VMOption> diagnosticVMOptions = mxBean.getDiagnosticOptions(); for (VMOption vmOption:diagnosticVMOptions){ System.out.println(vmOption.getName() + " = " + vmOption.getValue()); } } }
示例如下:
C:\Users\hu'nan>java -XX:+PrintFlagsInitial | findstr manageable
intx CMSAbortablePrecleanWaitMillis = 100 {manageable} {default}
intx CMSTriggerInterval = -1 {manageable} {default}
intx CMSWaitDuration = 2000 {manageable} {default}
bool HeapDumpAfterFullGC = false {manageable} {default}
bool HeapDumpBeforeFullGC = false {manageable} {default}
bool HeapDumpOnOutOfMemoryError = false {manageable} {default}
ccstr HeapDumpPath = {manageable} {default}
uintx MaxHeapFreeRatio = 70 {manageable} {default}
uintx MinHeapFreeRatio = 40 {manageable} {default}
bool PrintClassHistogram = false {manageable} {default}
bool PrintConcurrentLocks = false {manageable} {default}
C:\Users\hu'nan>jinfo -flag HeapDumpOnOutOfMemoryError 4580
-XX:-HeapDumpOnOutOfMemoryError
C:\Users\hu'nan>jinfo -flag +HeapDumpOnOutOfMemoryError 4580
C:\Users\hu'nan>jinfo -flag HeapDumpOnOutOfMemoryError 4580
-XX:+HeapDumpOnOutOfMemoryError
jmap是一个功能强大的堆内存查看工具,它可以生成java程序的堆Dump文件,也可以查看堆内对象实例的统计信息、ClassLoader信息以及finalizer队列。jmap的基本语法为:
C:\>jmap <option> <pid>
option
参数:
-dump:[live,]format=b,file=
:使用hprof二进制形式,输出jvm的heap内容到文件(live参数是可选的,当指定了live参数时,那么只输出存活对象到文件)
-finalizerinfo:打印正等候回收的对象的信息。
-histo[:live]:打印每个class的实例数、内存占用、全限定类名。 VM的内部类名字开头会加上前缀”*”,如果加上live参数,那么只统计存活对象数量。
-clstats:打印Java堆的类装载器的统计信息。
示例如下:
C:\Users\hu'nan>jmap -histo 4580
num #instances #bytes class name (module)
-------------------------------------------------------
1: 8421 958408 [B ([email protected])
2: 643 398560 [I ([email protected])
3: 1987 313384 [Ljava.lang.Object; ([email protected])
注意:在jdk8及以前,可以使用jhat命令分析,在jdk8之后,官方推荐使用VisualVM代替。
jstack命令可以用于查看应用程序的堆栈。常用语法为:
C:\Users\hu'nan>jstack [-l] <pid>
-l
是可选参数,指定它将会打印锁的附加信息。jstack命令会在控制台打印输出程序中所有的锁信息。
示例如下:
C:\Users\hu'nan>jstack -l 4580
2020-06-03 20:49:40
Full thread dump Java HotSpot(TM) 64-Bit Server VM (11.0.2+9-LTS mixed mode):
Threads class SMR info:
_java_thread_list=0x00000287b76019a0, length=12, elements={
0x00000287b662d800, 0x00000287b6637800, 0x00000287b6f0b000, 0x00000287b6f0c000,
0x00000287b6f0e800, 0x00000287b6f11800, 0x00000287b6647000, 0x00000287b70b3000,
0x00000287b72d0000, 0x00000287b72d4000, 0x00000287b77ba000, 0x0000028797b4d800
}
jstatd命令是一个RMI服务器端程序,可以通过它来建立本地计算机与远程服务器之间的通信。
jstatd参数如下:
-p
:设置RMI注册中心的端口号,默认为1099。-n
:设置远程RMI对象在RMI注册表中绑定到的名称。默认名称是JStatRemoteHost。-Joption/-J
:此选项将Java选项传递给JVM,其中该选项是Java应用程序启动程序的参考页面中描述的选项之一。例如,-J-Xms48m将启动内存设置为48mb。示例如下:
首先要创建一个jstatd.all.policy文件,在jdk8及以前需要写入:
grant codebase "file:F:/instrument/siki--java/java-11.0.2/lib/tools.jar" {
permission java.security.AllPermission;
};
因为jdk11里没有tools.jar,所以需要新的配置方法:
grant codebase "jrt:/jdk.jstatd" {
permission java.security.AllPermission;
};
grant codebase "jrt:/jdk.internal.jvmstat" {
permission java.security.AllPermission;
};
然后在命令行运行:
C:\Users\hu'nan>jstatd -J-Djava.security.policy=F:\instrument\siki--java\java-11.0.2\conf\jstatd.all.policy
jstatd started (bound to /JStatRemoteHost)
使用jps显示远程计算机的java程序:
C:\Users\big'kai>jps 192.168.1.103:1099
4580 ApplicationStart
10056 Jps
3912
18780 Launcher
jdk7以后新增了一个jcmd指令,它具有很多功能:导出堆、查看java进程、导出线程信息、执行GC、查看虚拟机状态等。jcmd命令可以对指定的java 虚拟机执行命令。jcmd -l
会列出当前系统运行的java虚拟机。
C:\Users\hu'nan>jcmd -l
4580 cn.bigkai.ApplicationStart
18360 jdk.jcmd/sun.tools.jcmd.JCmd -l
然后可以通过jcmd
的方式列出它们所支持的指令:
C:\Users\hu'nan>jcmd 4580 help
4580:
The following commands are available:
Compiler.CodeHeap_Ana(这个词是屏蔽词。。。)lytics
Compiler.codecache
Compiler.codelist
Compiler.directives_add
Compiler.directives_clear
Compiler.directives_print
Compiler.directives_remove
Compiler.queue
GC.class_histogram
GC.class_stats # 查看系统中类的统计信息
GC.finalizer_info
GC.heap_dump # 导出堆信息
GC.heap_info
GC.run
GC.run_finalization
JFR.check
JFR.configure
JFR.dump
JFR.start
JFR.stop
JVMTI.agent_load
JVMTI.data_dump
ManagementAgent.start
ManagementAgent.start_local
ManagementAgent.status
ManagementAgent.stop
Thread.print # 打印线程堆栈信息
VM.check_commercial_features
VM.class_hierarchy
VM.classloader_stats
VM.classloaders
VM.command_line
VM.dynlibs
VM.flags # 获取启动参数
VM.info
VM.log
VM.metaspace
VM.native_memory
VM.print_touched_methods
VM.set_flag # 设置启动弄参数
VM.stringtable
VM.symboltable
VM.system_properties # 获取系统的properties信息
VM.systemdictionary
VM.unlock_commercial_features
VM.uptime # 查看虚拟机启动时间
VM.version
help
For more information about a specific command use 'help <command>'.
还可以通过
jcmd 4580 PerfCounter.print 获取所有性能统计相关信息
。