JDK 工具

1. JDK 命令行工具

  • jps(查看 HotSpot 虚拟机进程) –> jstack(虚拟机进程中的线程快照)
  • jinfo(虚拟机配置信息) –> jstat(HotSpot 运行时的数据)
  • jmap(虚拟机内存快照 heapdump 文件) –> jhat(分析 heapdump 文件)

工具的实现都在 jdk/lib/tools.jar 类库

1.1. jps: 查看虚拟机进程

jsp (JVM process Status Tool),可以显示正在运行的 Java 进程,以及虚拟机执行的主类信息。

1.1.1. 命令格式

1
2
3
4
5
6
[root@test ~]# jps -help
usage: jps [-help]
jps [-q] [-mlvV] [<hostid>]

Definitions:
<hostid>: <hostname>[:<port>]

hostid 可以不填写,例如:

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
[root@test ~]# jps -mlv
30482 a.jar -s -num 1000
7532 b.jar
5533 sun.tools.jps.Jps -mlv -Dapplication.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.222.b10-0.el7_6.x86_64 -Xms8m
```

### 常用参数
| 选项 | 作用 |
|:-------------:|:--------|
| -m | 输出虚拟机进程启动时传递给主类 main() 函数的参数 |
| -l | 输出主类饿全名,如果进程执行的是 jar 包,输出 jar包路径 |
| -v | 输出虚拟机进程启动时的 JVM 参数|

## jstack
jstack (Stack Trace for Java ) 用户生成当前时刻的虚拟机线程快照。往往在排查 Java 进程 CPU 飙高,线程卡死,线程数升高,线程运行卡顿,线程死锁等问题,非常有效。(曾经解决过一个线程数量飙升的问题,就是利用这个工具,查处了有许多相同的线程)。

### 命令格式
```shell
[root@test ~]# jstack -help
Usage:
jstack [-l] <pid>
(to connect to running process)
jstack -F [-m] [-l] <pid>
(to connect to a hung process)
jstack [-m] [-l] <executable> <core>
(to connect to a core file)
jstack [-m] [-l] [server_id@]<remote server IP or hostname>
(to connect to a remote debug server)

Options:
-F to force a thread dump. Use when jstack <pid> does not respond (process is hung)
-m to print both java and native frames (mixed mode)
-l long listing. Prints additional information about locks
-h or -help to print this help message


[root@test ~]# jstack -l 30482
```

### 常用参数
| 选项 | 作用 |
|:-------------:|:--------|
| -F | 当正常输出的请求不被响应时,强制输出线程堆栈 |
| -l | 除堆栈外,显示关于锁的附加信息 |
| -m | 如果调用到本地方法的法(JNI), 可以显示 C/C++ 的堆栈|

### 获取虚拟机所有线程信息
JDK 1.5 中,java.lang.Thread.getAllStackTraces() 方法可以获取虚拟机栈中所有线程的 StackTraceElement 对象。使用这个方法可以通过几行简单的代码完成 jstack 大部分的功能。所以,可以做一个 html 页面,随时获取虚拟机堆栈的线程信息。

## jinfo
Java 配置信息工具,可以实时的查看和调整虚拟机运行期可写的参数。


### 命令格式
```shell
[root@test ~]# jinfo -help
Usage:
jinfo [option] <pid>
(to connect to running process)
jinfo [option] <executable <core>
(to connect to a core file)
jinfo [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)

where <option> is one of:
-flag <name> to print the value of the named VM flag
-flag [+|-]<name> to enable or disable the named VM flag
-flag <name>=<value> to set the named VM flag to the given value
-flags to print VM flags
-sysprops to print Java system properties
<no option> to print both of the above
-h | -help to print this help message


[root@test ~]# jinfo -flags 30482
Attaching to process ID 30482, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.222-b10
Non-default VM flags: -XX:CICompilerCount=12 -XX:InitialHeapSize=264241152 -XX:MaxHeapSize=4204789760 -XX:MaxNewSize=1401421824 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=88080384 -XX:OldSize=176160768 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseParallelGC
Command line:
```

### 常用参数
| 选项 | 作用 |
|:-------------:|:--------|
| -flags | 显示 VM 虚拟机的运行参数 |

### 修改虚拟机配置

```shell
jinfo -flag name=value
或者
jinfo -flag [+|-] name

1.1.2. java -XX:+PrintFlagsFinal 使用

注意 : JDK 1.6 及以上版本

可以通过 grep 命令过滤自己需要查询的参数默认值。

1.1.2.1. 命令格式

1
» java -XX:+PrintFlagsFinal -help  #查看帮助文档

比如,查看虚拟机默认的的堆内存大小:

1
2
3
4
5
6
7
8
9
» java -XX:+PrintFlagsFinal -version | grep -i  HeapSize
uintx ErgoHeapSizeLimit = 0 {product}
uintx HeapSizePerGCThread = 87241520 {product}
uintx InitialHeapSize := 268435456 {product}
uintx LargePageHeapSizeThreshold = 134217728 {product}
uintx MaxHeapSize := 4294967296 {product}
java version "1.8.0_161"
Java(TM) SE Runtime Environment (build 1.8.0_161-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.161-b12, mixed mode)

1.1.2.2. 物理内存和堆默认值的关系

物理内存 mem ,那么初始堆(InitialHeapSize)的大小 = mem * 1/64,最大值分两种情况:

  • 0 < mem < 192MB : 堆最大为在物理内存 50%(1/2)
  • 192MB < mem : 堆最大为在物理内存 25%(1/4)

我的电脑是 16G 内存,所以:
InitialHeapSize = 16/64 * 1024 * 1024 * 1024 = 268435456 = 256MB
MaxHeapSize = 16/4 * 1024 * 1024 * 1024 = 4294967296 = 4G

1.2. jstat

jstat 虚拟机统计信息监视工具,可以查看 JVM 当前各个区域的内存分配,GC 总次数和总耗费时长,而且可以定时刷新监控。

1.2.1. 命令格式

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# 帮助
» jstat -help
Usage: jstat -help|-options
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

Definitions:
<option> An option reported by the -options option
<vmid> Virtual Machine Identifier. A vmid takes the following form:
<lvmid>[@<hostname>[:<port>]]
Where <lvmid> is the local vm identifier for the target
Java virtual machine, typically a process id; <hostname> is
the name of the host running the target Java virtual machine;
and <port> is the port number for the rmiregistry on the
target host. See the jvmstat documentation for a more complete
description of the Virtual Machine Identifier.
<lines> Number of samples between header lines.
<interval> Sampling interval. The following forms are allowed:
<n>["ms"|"s"]
Where <n> is an integer and the suffix specifies the units as
milliseconds("ms") or seconds("s"). The default units are "ms".
<count> Number of samples to take before terminating.
-J<flag> Pass <flag> directly to the runtime system.

# 查看 options 可选参数列表
» jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
```

参数 interval 和 count 代表查询间隔和次数,如果省略这两个参数,表示只查询一次。假设,需要 250ms 查询一次进程 2764 的垃圾手机状况,一共查询 20 次,那命令应该是:

```shell
jstat -gc 2764 250 20

1.2.2. 常用参数

选项 作用
-class 监视类装载、卸载数量、总空间以及类装载锁耗费的时间
-gc 监视 JVM 堆状况,包括 Eden 区,两个 survivor 区、老年代、永久带等的容量、已用空间,GC 时间合计信息
-gccapacity 监视内容和 -gc 基本相同,但是输出主要关注 Java 堆各个区域的使用到的最大、最小空间
-gcutil 监视内容和 -gc 基本相同,但是输出主要关注已使用空间占总空间的百分比
-gccause 与 -gcutil 功能一样,但是会额外输出导致上一次 GC 产生的原因
-gcmetacapacity 输出 Meta Space 使用到的最大最小空间,以及 GC 情况
-gcnew 监视新生代 GC 状况
-gcnewcapacity 与 -gcnew 基本相同,输出主要是关注使用到的最大、最小空间
-gcold 监视老年代 GC 状况
-gcoldcapacity 与 -gcold 基本相同,输出主要是关注使用到的最大、最小空间
-compiler 输出 JIT 编译器编译过的方法,耗时等信息
-printcompilation 输出已经被 JIT 编译的方法

1.3. jmap

jmap(Memory Map for Java),Java 内存映像工具,用户堆快照生成,也就是我们说的 heapdump 文件。

1.3.1. 除开 jmap 获取 heapdump 文件的方式

1.3.1.1. -XX:+HeapDumpOnOutOfMemoryError 参数

如果不使用 jmap 命令,可以通过设置 -XX:+HeapDumpOnOutOfMemoryError 参数,在虚拟机出现 OOM 异常后自动生成 dump 文件。

1.3.1.2. -XX:+HeapDumpOnCtrlBreak 参数

该方式只能适用于 JDK 1.4.2_12 或者更高一级 1.5.0_14 或者更高。
JDK 1.6, 1.7, 1.8 已经移除了这种方式。

1.3.1.3. kill -3(还没找到生成的文件位置??)

Linux 系统下可以通过 kill -3 命令发送给 Java 进程退出信号“吓唬”一下虚拟机,也能拿到 dump 文件。

生成的 dump 文件目录在:

When ‘kill -3’ option is used thread dump is sent to the standard error stream. If you are running your application in tomcat, thread dump will be sent into /logs/catalina.out file.

##

1.3.2. 命令格式

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
28
29
30
31
32
33
34
35
36
» jmap -help
Usage:
jmap [option] <pid>
(to connect to running process)
jmap [option] <executable <core>
(to connect to a core file)
jmap [option] [server_id@]<remote server IP or hostname>
(to connect to remote debug server)

where <option> is one of:
<none> to print same info as Solaris pmap
-heap to print java heap summary
-histo[:live] to print histogram of java object heap; if the "live"
suboption is specified, only count live objects
-clstats to print class loader statistics
-finalizerinfo to print information on objects awaiting finalization
-dump:<dump-options> to dump java heap in hprof binary format
dump-options:
live dump only live objects; if not specified,
all objects in the heap are dumped.
format=b binary format
file=<file> dump heap to <file>
Example: jmap -dump:live,format=b,file=heap.bin <pid>
-F force. Use with -dump:<dump-options> <pid> or -histo
to force a heap dump or histogram when <pid> does not
respond. The "live" suboption is not supported
in this mode.
-h | -help to print this help message
-J<flag> to pass <flag> directly to the runtime system



# 例如
» jmap -dump:format=b,file='/Users/MoMo/Downloads/test.dump' 90965
Dumping heap to /Users/MoMo/Downloads/test.dump ...
Heap dump file created

1.3.3. 常用参数

选项 作用
-dump 生成 Java 堆转储快。格式为:-dump:[live,]format=b,file=,其中 live 子参数说明是否只 dump 存活的对象
-finalizerinfo 显示在 F-Queue 中等待 Finalizer 线程执行 finalize 方法的对象,只在 *ix 平台有效
-heap 显示 Java 堆详细信息,如使用哪种回收期、参数配置、分代状况等,只在 *ix 平台有效
-histo 显示对象统计信息,包括类、实例数量、合计容量
-F 如果 -dump 没有响应,使用 -F 强制生成 dump 快照

1.4. jhat

jhat(JVM Heap Analysis Tool),虚拟机转存快照分析工具,与 jmap 搭配使用。但是这个命令不常用,原因两个:

  1. 命令行工具限制太多
  2. 分析功能相对比较简陋

常用做法是把 dump 文件下载到本地,使用 Visual VM 或者 Eclipse Memory Analyzer 等工具来分析。

1.5. HSDIS

HSDIS 是一个 Sun 官方推荐的 HotSpot 虚拟机 JIT 编译代码的反汇编插件,包含在 HotSpot 虚拟机的源码种植,但是没有提供编译后的程序。

2. JVM 可视化工具

2.1. JConsle

2.2. VisualVM

Just for my love !!