目录
- 前言
- 一、jps:虚拟机进程状况工具
- 一、一 输出远程机器信息
- 二、jstat:虚拟机统计信息监视工具
- 三、jinfo: Java配置信息工具
- 四、jmap: Java内存映像工具
- 五、jhat:虚拟机堆转储快照分析工具
- 六、jstack: Java堆栈跟踪工具
- 七、基础工具总结
前言
大家都知道JDK的bin目录中有java.exe、 javac.exe这样的命令行工具,这些工具主要是用于监视虚拟机运行状态和进行故障处理的工具。这些故障处理工具并不单纯是被Oracle公司作为“礼物”附赠给JDK的使用者,根据软件可用性和授权的不同,可以把它们划分成三类:
- 商业授权工具: 主要是JMC(Java Mission Control)及它要使用到的JFR(Java Flight Recorder),JMC这个原本来自于JRockit的运维监控套件从JDK 7 Update 40开始就被集成到OracleJDK中,
JDK11之前都无须独立下载,但是在商业环境中使用它则是要付费的。
- 正式支持工具:这一类工具属于被长期支持的工具,不同平台、不同版本的JDK之间,这类工具可能会略有差异,但是不会出现某一个工具突然消失的情况。
- 实验性工具: 这一类工具在它们的使用说明中被声明为“没有技术支持,并且是实验性质的”(Unsupported and Experimental)产品,日后可能会转正,也可能会在某个JDK版本中无声无息地消失。但事实上它们通常都非常稳定而且功能强大,也能在处理应用程序性能问题、定位故障时发挥很大的作用。
一、jps:虚拟机进程状况工具
jps( JVM Process Status Tool)功能:可以列出正在运行的虚拟机进程,并显示虚拟机执行主类( Main Class,main()函数所在的类)名称以及这些进程的本地虚拟机唯一ID( LVMID, Local Virtual Machine Identifier)。
命令格式:
jps [ options ] [ hostid ]
示例:
jps
1764 RemoteMavenServer
18516 Launcher
17868 Jps
选项:
选项 | 描述 |
---|---|
-q | 只输出进程ID,忽略主类信息 |
-l | 输出主类全名,或者执行JAR包则输出路径 |
-m | 输出虚拟机进程启动时传递给主类main()函数的参数 |
-v | 输出虚拟机进程启动时的JVM参数 |
一、一 输出远程机器信息
jps还可以通过RMI协议查询开启了RMI服务的远程虚拟机进程状态,参数hostid为RMI注册表中注册的主机名。
jps 链接远程输出JVM信息,需要注册RMI,否则会报错:
jps -lv 127.0.0.1
RMI Registry not available at 127.0.0.1:1099
Connection refused to host: 127.0.0.1; nested exception is:
java.net.ConnectException: Connection refused: connect
1、注册RMI开启 jstatd 在你的C:\Program Files\Java\jdk1.8.0_91\bin
目录下添加名称为 jstatd.all.policy 的文件。
jstatd.all.policy 文件内容如下:
grant codebase "file:${java.home}/../lib/tools.jar" {
permission java.security.AllPermission;
};
2、添加好配置文件后,在 bin 目录下注册添加的 jstatd.all.policy 文件:
C:\Program Files\Java\jdk1.8.0_91\bin>jstatd -J-Djava.security.policy=jstatd.all.policy
成功示例如下:
C:\Users\Administrator>jps -lv 127.0.0.1
12708 sun.tools.jps.Jps -Denv.class.path=.;G:\Java\jdk1.8.0_91\lib\dt.jar;G:\Java\jdk1.8.0_91\lib\tools.jar; -Dapplication.home=C:\Program Files\Java\jdk1.8.0_91 -Xms8m
16116 exit -Xms128m -Xmx3096m -XX:ReservedCodeCacheSize=512m -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=100 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -XX:+HeapDumpOnOutOfMemoryError
-Didea.vendor.name=JetBrains -Didea.paths.selector=IntelliJIdea2021.1 -XX:ErrorFile=C:\Users\Administrator\java_error_in_idea64_%p.log -XX:HeapDumpPath=C:\Users\Administrator\java_error_in_idea64.hprof
1764 org.jetbrains.idea.maven.server.RemoteMavenServer -Djava.awt.headless=true -Dmaven.defaultProjectBuilder.disableGlobalModelCache=true -Didea.version=2021.1.2 -Didea.maven.embedder.version=3.1.1 -Xmx768m -Dfile.e
18516 org.jetbrains.jps.cmdline.Launcher -Xmx700m -Djava.awt.headless=true -Djava.endorsed.dirs="" -Djdt.compiler.useSingleThread=true -Dpreload.project.path=G:/ideawork -Dpreload.config.path=G:/IntelliJ IDEA 2021.1.
net.preferIPv4Stack=true -Dio.netty.initialSeedUniquifier=1570513135976058670 -Dfile.encoding=GBK -Duser.language=zh -Duser.country=CN -Didea.paths.selector=IntelliJIdea2021.1 -Didea.home.path=G:\IntelliJ IDEA 2021.1
a2021.1/.IntelliJIdea/system/log/build-log -Djps.fallback.jdk.hom
2684 sun.tools.jstatd.Jstatd -Denv.class.path=.;G:\Java\jdk1.8.0_91\lib\dt.jar;G:\Java\jdk1.8.0_91\lib\tools.jar; -Dapplication.home=C:\Program Files\Java\jdk1.8.0_91 -Xms8m -Djava.security.policy=jstatd.all.policy
参数组合:
jps -lm 127.0.0.1
二、jstat:虚拟机统计信息监视工具
jstat(JVM Statistics Monitoring Tool),用于监视虚拟机各种运行状态信息。它可以查看本地或者远程虚拟机进程中,类加载、内存、垃圾收集、即时编译等运行时数据。
命令格式:
jstat [ option vmid [interval[s|ms] [count]] ]
vmid:如果是查看远程机器,需要按照此格式:
[protocol:][//]lvmid[@hostname[:port]/servername]
interval和count,表示查询间隔和次数,比如每隔1000毫秒查询一次进程ID的gc收集情况,每次查询5次。
jstat -gc 111552 1000 3
选项主要分为三类:类加载、垃圾收集、运行期编译状况:
选项 | 描述 |
---|---|
-class | 监视类加载、卸载数量、总空间以及类装载所耗费时长 |
-gc | 监视 Java 堆情况,包括Eden区、2个 Survivor区、老年代、永久代或者jdk1.8元空间等,容量、已用空间、垃圾收集时间合计等信息 |
-gccapacity | 监视内容与-gc基本一致,但输出主要关注 Java 堆各个区域使用到的最大、最小空间 |
-gcutil | 监视内容与-gc基本相同,但输出主要关注已使用空间占总空间的百分比 |
-gccause | 与 -gcutil 功能一样,但是会额外输出导致上一次垃圾收集产生的原因 |
-gcnew | 监视新生代垃圾收集情况 |
-gcnewcapacity | 监视内容与 -gcnew 基本相同,输出主要关注使用到的最大、最小空间 |
-gcold | 监视老年代垃圾收集情况 |
-gcoldcapacity | 监视内容与 -gcold 基本相同,输出主要关注使用到的最大、最小空间 |
-compiler | 输出即时编译器编译过的方法、耗时等信息 |
-printcompilation | 输出已经被即时编译的方法 |
-gcpermcapacity | jdk1.7 及以下,永久代空间统计 |
-gcmetacapacity | jdk1.8,元空间统计 |
示例:
C:\Users\Administrator>jstat -class 14944 1000 5
Loaded Bytes Unloaded Bytes Time
6216 11190.6 1 0.9 4.70
6216 11190.6 1 0.9 4.70
6216 11190.6 1 0.9 4.70
C:\Users\Administrator>jstat -compiler 14944 1000 5
Compiled Failed Invalid Time FailedType FailedMethod
3290 0 0 7.73 0
3290 0 0 7.73 0
C:\Users\Administrator>jstat -gcutil 14944 1000 5
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT
0.00 34.71 89.33 6.49 94.64 91.92 5 0.080 1 0.048 0.128
0.00 34.71 89.33 6.49 94.64 91.92 5 0.080 1 0.048 0.128
C:\Users\Administrator>jstat -gc 14944 1000 5
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC
6656.0 10752.0 0.0 3732.1 131072.0 117082.2 82944.0 5384.1 28416.0 26893.9 3840.0 3529.8 5 0.080 1
三、jinfo: Java配置信息工具
jinfo( Configuration Info for Java)的作用是实时查看和调整虚拟机各项参数。
命令格式:
jinfo [ option ] pid
示例:
C:\Users\Administrator>jinfo -flag MetaspaceSize 14944
-XX:MetaspaceSize=21807104
四、jmap: Java内存映像工具
jmap( Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文件)。如果不使用jmap命令,要想获取Java堆转储快照也还有一些比较“暴力”的手段:例如-XX: +HeapDumpOnOutOfMemoryError参数,可以让虚拟机在内存溢出异常出现之后自动生成堆转储快照文件,通过-XX: +HeapDumpOnCtrlBreak参数则可以使用[Ctrl]+[Break]键让虚拟机生成堆转储快照文件,又或者在Linux系统下通过Kill-3命令发送进程退出信号“恐吓”一下虚拟机,也能顺利拿到堆转储快照。
jmap的作用并不仅仅是为了获取堆转储快照,它还可以查询finalize执行队列、 Java堆和方法区的详细信息,如空间使用率、当前用的是哪种收集器等。
命令格式:
jmap [ option ] pid
option:选项参数
pid:需要打印配置信息的进程ID
executable:产生核心dump的Java可执行文件
core:需要打印配置信息的核心文件
server-id:可选的唯一id,如果相同的远程主机上运行了多台调试服务器,用此选项参数标识服务器
remote server IP or hostname: 远程调试服务器的IP地址或主机名
选项:
选项 | 描述 |
---|---|
-dump | 生成 Java 堆转储快照。 |
-finalizerinfo | 显示在F-Queue中等待Finalizer线程执行finalize方法的对象。Linux平台 |
-heap | 显示 Java 堆详细信息,比如:用了哪种回收器、参数配置、分代情况。Linux平台 |
-histo | 显示堆中对象统计信息,包括类、实例数量、合计容量 |
-permstat | 显示永久代内存状态,jdk1.7,永久代 |
-F | 当虚拟机进程对 -dump 选项没有响应式,可以强制生成快照。Linux平台 |
堆转储文件示例:
jmap -dump:live,format=b,file=heap.bin 14944
C:\Users\Administrator>jmap -dump:format=b,file=idea.bin 14944
Dumping heap to C:\Users\Administrator\idea.bin ...
Heap dump file created
打印加载类示例:
C:\Users\Administrator>jmap -clstats 14944
Attaching to process ID 14944, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.91-b15
finding class loader instances ..done.
computing per loader stat ..done.
please wait.. computing liveness.......liveness analysis may be inaccurate ...
class_loader classes bytes parent_loader alive? type
<bootstrap> 1698 2983149 null live <internal>
0x00000007736a41e8 1 880 0x00000006c1c14038 dead sun/reflect/DelegatingClassL
五、jhat:虚拟机堆转储快照分析工具
JDK提供jhat( JVM Heap Analysis Tool)命令与jmap搭配使用,来分析jmap生成的堆转储快照。jhat内置了一个微型的HTTP/Web服务器,生成堆转储快照的分析结果后,可以在浏览器中查看。
不过在实际工作中,除非手上真的没有别的工具可用,否则多数人是不会直接使用jhat命令来分析堆转储快照文件的,主要原因有两个方面:
一是一般不会在部署应用程序的服务器上直接分析堆转储快照,即使可以这样做,也会尽量将堆转储快照文件复制到其他机器上进行分析,因为分析工作是一个耗时而且极为耗费硬件资源的过程,既然都要在其他机器上进行,就没有必要再受命令行工具的限制了。
另外一个原因是jhat的分析功能相对来说比较简陋,后文将会介绍到的VisualVM,以及专业用于分析堆转储快照文件的Eclipse Memory Analyzer、 IBM HeapAnalyzer等工具,都能实现比jhat更强大专业的分析功能。下列代码清单演示了使用jhat分析上一节采用jmap生成的Eclipse IDE的内存快照文件。
示例:
C:\Users\Administrator>jhat idea.bin
Reading from idea.bin...
Dump file created Wed Oct 26 20:48:34 CST 2022
Snapshot read, resolving...
Resolving 1394404 objects...
Chasing references, expect 278 dots...................................................................................
Eliminating duplicate references......................................................................................
Snapshot resolved.
Started HTTP server on port 7000
Server is ready.
屏幕显示“Server is ready.”的提示后,用户在浏览器中输入http://localhost:7000/可以看到分析结果,如图所示。
分析结果默认以包为单位进行分组显示,分析内存泄漏问题主要会使用到其中的“Heap Histogram”(与jmap-histo功能一样)与OQL页签的功能,前者可以找到内存中总容量最大的对象,后者是标准的对象查询语言,使用类似SQL的语法对内存中的对象进行查询统计。
六、jstack: Java堆栈跟踪工具
jstack( Stack Trace for Java)命令用于生成虚拟机当前时刻的线程快照(一般称为threaddump或者javacore文件)。线程快照就是当前虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的目的通常是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间挂起等,都是导致线程长时间停顿的常见原因。线程出现停顿时通过jstack来查看各个线程的调用堆栈,就可以获知没有响应的线程到底在后台做些什么事情,或者等待着什么资源。
命令格式:
jstack [ option ] vmid
选项:
选项 | 描述 |
---|---|
-F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
-l | 除了堆栈外,显示关于锁的附加信息 |
-m | 如果调用的是本地方法的话,可以显示c/c++的堆栈 |
示例:
jstack -l 14944
从JDK 5起, java.lang.Thread类新增了一个getAllStackTraces()方法用于获取虚拟机中所有线程的StackTraceElement对象。使用这个方法可以通过简单的几行代码完成jstack的大部分功能,在实际项目中不妨调用这个方法做个管理员页面,可以随时使用浏览器来查看线程堆栈,如下述代码清单所示。
<%@ page import="java.util.Map"%>
<html>
<head>
<title>服务器线程信息</title>
</head>
<body>
<pre>
<%
for (Map.Entry<Thread, StackTraceElement[]> stackTrace : Thread.getAllStack-Traces().entrySet()) {
Thread thread = (Thread) stackTrace.getKey();
StackTraceElement[] stack = (StackTraceElement[]) stackTrace.getValue();
if (thread.equals(Thread.currentThread())) {
continue;
}
out.print("\n线程: " + thread.getName() + "\n");
for (StackTraceElement element : stack) {
out.print("\t"+element+"\n");
}
}
%>
</pre>
</body>
</html>
七、基础工具总结
下面表罗列了JDK附带的全部(包括曾经存在但已经在最新版本中被移除的)工具及其简要用途,在高版本的JDK中,这些工具大多已有了功能更为强大的替代品,例如JCMD、 JHSDB的命令行模式,但使用方法也是相似的,无论JDK发展到了什么版本,学习这些基础的工具命令并不会过时和浪费。
-
基础工具:用于支持基本的程序创建和运行。
-
安全:用于程序签名、设置安全测试等。
-
国际化:用于创建本地语言文件。
-
远程方法调用:用于跨Web或网络的服务交互。
Java IDL与RMI-IIOP:在JDK 11中结束了十余年的CORBA支持,这些工具不再提供。
-
部署工具:用于程序打包、发布和部署。
-
Java Web Start。
-
性能监控和故障处理:用于监控分析Java虚拟机运行信息,排查问题。
-
WebService工具:与CORBA一起在JDK 11中被移除。
-
REPL和脚本工具。
点赞 收藏 关注
外事以刚日,内事以柔日