JDK常用命令实战

前言:

作为一名专业的java开发工程师,每每都会遇到JVM相关的问题,多在于full GC过多、超时,内存参数设置异常,或者查看异常的线程信息。

这些问题,本质上并不复杂,只要我们选择合适的工具就很简单。

那么有哪些工具呢?JDK自身就提供了很多可靠的工具。本文就来看下JDK提供的那些实用命令工具。

注意:笔者使用的是Windows机器,JDK安装位置为D:\Program Files\Java\jdk1.8.0_131

这些命令所在位置就是%JDK_HOME%\bin目录下

1.jinfo命令

jinfo命令主要用于观察进程运行环境参数,包括java system属性和JVM命令行参数

1.1 命令参数

jinfo命令主要使用方式如下:

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jinfo.exe
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

多的不需要演示,实在不知道用哪一个,就用一个命令就可以了 jinfo [pid]

1.2 常用命令jinfo [pid]

笔者已经启动一个java应用,使用jps查看进程id

PS D:\Program Files\Java\jdk1.8.0_131\bin> jps
17648 Launcher
3424
1588 Jps
15276 Bootstrap

我们直接使用jinfo 15276 查看这个进程的相关信息

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jinfo.exe 15276

Attaching to process ID 15276, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
Java System Properties:

...

java.vm.name = Java HotSpot(TM) 64-Bit Server VM
file.encoding = GBK
com.sun.management.jmxremote.password.file = C:\Users\lucky\.IntelliJIdea2019.1\system\tomcat\Unnamed_SpringTest\jmxremote.password
java.specification.version = 1.8

...

java.vendor = Oracle Corporation
sun.java.launcher = SUN_STANDARD
catalina.base = C:\Users\lucky\.IntelliJIdea2019.1\system\tomcat\Unnamed_SpringTest
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
catalina.useNaming = true
os.name = Windows 10
VM Flags:
Non-default VM flags: -XX:CICompilerCount=3 -XX:InitialHeapSize=1073741824 -XX:+ManagementServer -XX:MaxHeapSize=1073741824 -XX:MaxNewSize=357564416 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=357564416 -XX:OldSize=716177408 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -Djava.util.logging.config.file=C:\Users\lucky\.IntelliJIdea2019.1\system\tomcat\Unnamed_SpringTest\conf\logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xmx1G -Xms1G -Dcom.sun.management.jmxremote= -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.password.file=C:\Users\lucky\.IntelliJIdea2019.1\system\tomcat\Unnamed_SpringTest\jmxremote.password -Dcom.sun.management.jmxremote.access.file=C:\Users\lucky\.IntelliJIdea2019.1\system\tomcat\Unnamed_SpringTest\jmxremote.access -Djava.rmi.server.hostname=127.0.0.1 -Djdk.tls.ephemeralDHKeySize=2048 -Djava.endorsed.dirs=D:\software\work-software\apache-tomcat-7.0.77\endorsed -Dcatalina.base=C:\Users\lucky\.IntelliJIdea2019.1\system\tomcat\Unnamed_SpringTest -Dcatalina.home=D:\software\work-software\apache-tomcat-7.0.77 -Djava.io.tmpdir=D:\software\work-software\apache-tomcat-7.0.77\temp

这样,所有的进程信息都打印出来了,直接查看即可。

2.jmap命令

主要用于监视进程运行中的jvm物理内存的占用情况。

该进程内存中,所有对象的情况:产生了哪些对象,对象数量

2.1 命令参数

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jmap.exe
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

下面我们把常用命令列举下

2.2 jmap -heap [pid]

查看当前进程堆内存信息

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jmap.exe -heap 15276
Attaching to process ID 15276, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11

using thread-local object allocation.
Parallel GC with 4 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 0
   MaxHeapFreeRatio         = 100
   MaxHeapSize              = 1073741824 (1024.0MB)
   NewSize                  = 357564416 (341.0MB)
   MaxNewSize               = 357564416 (341.0MB)
   OldSize                  = 716177408 (683.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 = 175112192 (167.0MB)
   used     = 175064104 (166.95413970947266MB)
   free     = 48088 (0.04586029052734375MB)
   99.97253874818722% used
From Space:
   capacity = 82313216 (78.5MB)
   used     = 0 (0.0MB)
   free     = 82313216 (78.5MB)
   0.0% used
To Space:
   capacity = 91226112 (87.0MB)
   used     = 0 (0.0MB)
   free     = 91226112 (87.0MB)
   0.0% used
PS Old Generation
   capacity = 716177408 (683.0MB)
   used     = 712284288 (679.2872314453125MB)
   free     = 3893120 (3.7127685546875MB)
   99.45640284704429% used

16144 interned Strings occupying 2101048 bytes.

特别详细的展示了堆内存空间的各种参数和当前使用情况

2.3 jmap -histo [pid]

列出当前内存中存活对象的柱状图,也就是对象个数以及占用内存信息

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jmap.exe -histo 15276

 num     #instances         #bytes  class name
----------------------------------------------
   1:           118      864029648  [Ljava.lang.Byte;
   2:         48058        9365704  [C
   3:          1435        2274008  [B
   4:          3179        1411832  [I
   5:         45365        1088760  java.lang.String
   6:          5795         660416  java.lang.Class
   7:         12701         406432  java.util.HashMap$Node
   8:          4459         392392  java.lang.reflect.Method
   9:          6174         373728  [Ljava.lang.Object;
  10:         10104         323328  java.util.concurrent.ConcurrentHashMap$Node
  11:          1184         209456  [Ljava.util.HashMap$Node;
  12:          2292         128912  [Ljava.lang.String;
  13:           160         127328  [Ljava.util.concurrent.ConcurrentHashMap$Node;
  ...

平时参考意义不是很大,但是如果发生内存泄露等问题时,还有有参考价值的。

2.4 jmap -clstats [pid]

主要展示ClassLoader信息

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jmap.exe -clstats 15276
Attaching to process ID 15276, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.131-b11
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>     2810    4889269   null          live    <internal>
0x00000000c0057f00      99      282157  0x00000000c0057f60      live    sun/misc/Launcher$AppClassLoader@0x000000010000f6a0
0x00000000c06554a0      1       1473    0x00000000c0118260      dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000c0655ae0      1       1473    0x00000000c0118260      dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000c0656120      1       1473    0x00000000c0118260      dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000d75fd4d8      1       880       null          dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000f4cf7908      1       1471      null          dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000c0655568      1       1473    0x00000000c0118260      dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000c0655ba8      1       1473    0x00000000c0118260      dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000d75fccd0      1       878       null          dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000d75fd410      1       880       null          dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
0x00000000c0655630      1       1473    0x00000000c0118260      dead    sun/reflect/DelegatingClassLoader@0x0000000100009df8
...

2.5 jmap -dump:format=b,file=heapdump.phrof [pid]

这个比较有用,可以打印出当前进程的dump信息

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jmap.exe  -dump:format=b,file=heapdump.phrof 15276
Dumping heap to D:\Program Files\Java\jdk1.8.0_131\bin\heapdump.phrof ...
Heap dump file created

这里打印出来的headdump.phrof文件,可以通过专业工具进行分析。后续笔者再在其他文章中进行单独分析。

3.jstat

jstat命令利用JVM内建的指令对java应用程序的资源和性能进行实时的命令行的监控,包括对进程的ClassLoader、compile、gc等情况。

3.1 命令参数

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jstat.exe
invalid argument count
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.

我们看这个命令的组成,中间具体的 <option> 有哪些呢?可以通过jstat -options来获取

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jstat.exe -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation

貌似也没个解释,笔者从网上找来各个option的含义,如下所示:

-class:统计class loader行为信息 
-compile:统计编译行为信息 
-gc:统计jdk gc时heap信息 
-gccapacity:统计不同的generations(包括新生区,老年区,permanent区)相应的heap容量情况 
-gccause:统计gc的情况,(同-gcutil)和引起gc的事件 
-gcnew:统计gc时,新生代的情况 
-gcnewcapacity:统计gc时,新生代heap容量 
-gcold:统计gc时,老年区的情况 
-gcoldcapacity:统计gc时,老年区heap容量 
-gcpermcapacity:统计gc时,permanent区heap容量 
-gcutil:统计gc时,heap情况

看样子统计了很多heap gc情况。

有那么多,具体使用的时候用哪个呢?当然你如果记得那就找对应的option即可,如果像笔者一样懒,那就记得两个option即可:-gc -gcutil

3.2 jstat -gc [pid] [<interval> [<count>]]

-gc命令查看当前进程的GC情况,包括老年代和新生代

这里的interval默认单位是ms,count是总打印次数

# 每秒打印一条当前jvm gc信息,总共打印10条
PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jstat.exe -gc 15276 1000 10
 S0C    S1C    S0U    S1U      EC       EU        OC         OU       MC     MU    CCSC   CCSU   YGC     YGCT    FGC    FGCT     GCT
80384.0 89088.0  0.0    0.0   171008.0 169991.8  699392.0   695588.3  34176.0 33212.7 3968.0 3650.6     10    0.635  121    29.864   30.499
80384.0 89088.0  0.0    0.0   171008.0 170271.4  699392.0   695588.3  34176.0 33212.7 3968.0 3650.6     10    0.635  123    30.134   30.769
80384.0 89088.0  0.0    0.0   171008.0 166144.3  699392.0   695589.5  34176.0 33220.1 3968.0 3650.6     10    0.635  127    31.064   31.699
80384.0 89088.0  0.0    0.0   171008.0 171008.0  699392.0   695589.4  34176.0 33221.4 3968.0 3650.6     10    0.635  131    32.047   32.682
80384.0 89088.0  0.0    0.0   171008.0 171008.0  699392.0   695589.4  34176.0 33223.4 3968.0 3650.6     10    0.635  135    33.045   33.680
80384.0 89088.0  0.0    0.0   171008.0 170952.0  699392.0   695589.4  34176.0 33227.1 3968.0 3651.1     10    0.635  139    34.043   34.679
80384.0 89088.0  0.0    0.0   171008.0 171008.0  699392.0   695589.4  34176.0 33227.2 3968.0 3651.1     10    0.635  144    35.107   35.742
80384.0 89088.0  0.0    0.0   171008.0 171008.0  699392.0   695589.4  34176.0 33231.3 3968.0 3651.2     10    0.635  148    36.068   36.703
80384.0 89088.0  0.0    0.0   171008.0 166260.6  699392.0   695587.7  34176.0 33243.8 3968.0 3651.7     10    0.635  152    37.235   37.870
80384.0 89088.0  0.0    0.0   171008.0 167297.5  699392.0   695587.7  34176.0 33245.0 3968.0 3651.7     10    0.635  156    38.156   38.792

这些输出值都是什么含义呢?

S0C:Current survivor space 0 capacity (KB).

S1C:Current survivor space 1 capacity (KB).

S0U:Current survivor space 0 utilization (KB).

S1U:Current survivor space 1 utilization (KB).

EC:Current eden space capacity (KB).

EU:Eden space utilization (KB).

OC:Current old space capacity (KB).

OU:Old space utilization (KB).

PC:Current permanent space capacity (KB).

PU:Permanent space utilization (KB).

YGC:Number of young generation GC Events.

YGCT:Young generation garbage collection time.

FGC:Number of full GC events.

FGCT:Full garbage collection time.

GCT:Total garbage collection time.

重点需要关注哪些呢?

笔者觉得比较重要的是YGC(young gc发生的次数)、YGCT(young gc所消耗的时间)、FGC(full gc发生的次数)、FGCT(full gc所消耗的时间)

只关注这些就可以了。

3.3 jstat -gcutil [pid] [<interval> [<count>]]

这个与-gc有什么区别呢?

本质上来说,基本没有区别,唯一的区别就是,-gcutil按照百分比的方式来展示的

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jstat.exe -gcutil 15276 1000 10
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  0.00   0.00  98.80  99.46  96.85  92.08     10    0.635   304   78.144   78.779
  0.00   0.00  98.80  99.46  96.85  92.08     10    0.635   304   78.144   78.779
  0.00   0.00  98.80  99.46  96.85  92.08     10    0.635   304   78.144   78.779
  0.00   0.00  98.82  99.46  96.85  92.08     10    0.635   305   78.144   78.779
  0.00   0.00  97.68  99.45  96.92  92.08     10    0.635   309   79.405   80.040
  0.00   0.00  97.64  99.45  96.94  92.08     10    0.635   314   80.540   81.175
  0.00   0.00  97.64  99.45  96.94  92.08     10    0.635   318   81.559   82.195
  0.00   0.00  97.64  99.45  96.94  92.08     10    0.635   321   82.466   83.101
  0.00   0.00  97.64  99.45  96.94  92.08     10    0.635   324   83.356   83.991
  0.00   0.00  97.64  99.45  96.94  92.08     10    0.635   328   84.654   85.289

可以看到,前面展示的Eden区 s1 s0区的展示变成百分比的方式了

4.jstack

jstack这个命令平时我们应该用的比较多。主要用来查看当前进程的线程信息

4.1 命令参数

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jstack.exe
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

4.2 jstack [pid]

直接查看进程线程信息。

这样直接使用的话,会把进程的线程信息直接打印到控制台,一般来说,都打印到一个文件里

PS D:\Program Files\Java\jdk1.8.0_131\bin> .\jstack.exe 15276 > stack.txt

直接打印到当前目录下 stack.txt文件里。我们看下该文件内容:

2022-03-20 18:47:07
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.131-b11 mixed mode):

"http-bio-8080-exec-76" #117 daemon prio=5 os_prio=0 tid=0x0000000017c37800 nid=0x5070 waiting on condition [0x000000001fb0e000]
   java.lang.Thread.State: WAITING (parking)
	at sun.misc.Unsafe.park(Native Method)
	- parking to wait for  <0x00000000c04be780> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
	at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
	at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
	at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:104)
	at org.apache.tomcat.util.threads.TaskQueue.take(TaskQueue.java:32)
	at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
    ...

当前线程名(http-bio-8080-exec-76)、线程状态(WAITING)、等待条件(0x000000001fb0e000)等信息都打印出来了。

总结:

JDK的工具中当然不止笔者上述介绍的这些,但是最常用的也就是目前这些了。

熟练掌握工具,不再惧怕任何问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恐龙弟旺仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值