jdk自带命令工具

JAVA_HOME/bin目录中有很多有用的命令:jps、jstat、jinfo、jmap、jhat、jstack。本文以监听2181端口的zookeeper应用为例讲解。

jps:虚拟机进程状况工具

jps -mlv

如下:

[root@centos4 bin]# jps -mlv
1366 org.apache.zookeeper.server.quorum.QuorumPeerMain ../config/zookeeper.properties -Xmx512M -Xms512M -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+DisableExplicitGC -Djava.awt.headless=true -Xloggc:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../logs/zookeeper-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../logs -Dlog4j.configuration=file:./../config/log4j.properties
2839 kafka.Kafka ../config/server.properties -Xmx1G -Xms1G -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+DisableExplicitGC -Djava.awt.headless=true -Xloggc:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../logs/kafkaServer-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../logs -Dlog4j.configuration=file:./../config/log4j.properties
6167 sun.tools.jps.Jps -mlv -Dapplication.home=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64 -Xms8m

jstat:虚拟机统计信息监视工具

[root@centos4 bin]# jstat
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查看,如下:

[root@centos4 bin]# jstat -options
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation

最常用的是-gcutil。

jinfo:Java配置信息工具

[root@centos4 app]# jinfo 
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后面如果不跟任何option,直接跟pid的话,会打印出VM信息和系统信息,最全。如下:

[root@centos4 app]# jinfo 1366
Attaching to process ID 1366, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12
Java System Properties:

com.sun.management.jmxremote.authenticate = false
java.runtime.name = OpenJDK Runtime Environment
java.vm.version = 25.191-b12
sun.boot.library.path = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/jre/lib/amd64
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
path.separator = :
java.rmi.server.randomIDs = true
file.encoding.pkg = sun.io
java.vm.name = OpenJDK 64-Bit Server VM
sun.java.launcher = SUN_STANDARD
user.country = US
user.dir = /home/koushengrui/app/kafka_2.11-0.10.2.0/bin
java.vm.specification.name = Java Virtual Machine Specification
java.runtime.version = 1.8.0_191-b12
os.arch = amd64
java.endorsed.dirs = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/jre/lib/endorsed
line.separator = 
java.vm.specification.vendor = Oracle Corporation
os.name = Linux
log4j.configuration = file:./../config/log4j.properties
sun.jnu.encoding = UTF-8
java.library.path = /usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
java.specification.name = Java Platform API Specification
java.class.version = 52.0
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
os.version = 3.10.0-693.el7.x86_64
user.home = /root
user.timezone = Asia/Shanghai
java.awt.printerjob = sun.print.PSPrinterJob
file.encoding = UTF-8
java.specification.version = 1.8
user.name = root
java.class.path = :/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/aopalliance-repackaged-2.5.0-b05.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/argparse4j-0.7.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/connect-api-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/connect-file-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/connect-json-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/connect-runtime-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/connect-transforms-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/guava-18.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/hk2-api-2.5.0-b05.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/hk2-locator-2.5.0-b05.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/hk2-utils-2.5.0-b05.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jackson-annotations-2.8.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jackson-annotations-2.8.5.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jackson-core-2.8.5.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jackson-databind-2.8.5.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jackson-jaxrs-base-2.8.5.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jackson-jaxrs-json-provider-2.8.5.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jackson-module-jaxb-annotations-2.8.5.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/javassist-3.20.0-GA.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/javax.annotation-api-1.2.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/javax.inject-1.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/javax.inject-2.5.0-b05.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/javax.servlet-api-3.1.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/javax.ws.rs-api-2.0.1.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jersey-client-2.24.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jersey-common-2.24.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jersey-container-servlet-2.24.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jersey-container-servlet-core-2.24.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jersey-guava-2.24.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jersey-media-jaxb-2.24.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jersey-server-2.24.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-continuation-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-http-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-io-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-security-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-server-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-servlet-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-servlets-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jetty-util-9.2.15.v20160210.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/jopt-simple-5.0.3.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka_2.11-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka_2.11-0.10.2.0-sources.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka_2.11-0.10.2.0-test-sources.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka-clients-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka-log4j-appender-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka-streams-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka-streams-examples-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/kafka-tools-0.10.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/log4j-1.2.17.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/lz4-1.3.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/metrics-core-2.2.0.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/osgi-resource-locator-1.0.1.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/reflections-0.9.10.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/rocksdbjni-5.0.1.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/scala-library-2.11.8.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/scala-parser-combinators_2.11-1.0.4.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/slf4j-api-1.7.21.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/slf4j-log4j12-1.7.21.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/snappy-java-1.1.2.6.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/validation-api-1.1.0.Final.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/zkclient-0.10.jar:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../libs/zookeeper-3.4.9.jar
kafka.logs.dir = /home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../logs
java.vm.specification.version = 1.8
sun.java.command = org.apache.zookeeper.server.quorum.QuorumPeerMain ../config/zookeeper.properties
java.home = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/jre
user.language = en
java.vm.info = mixed mode
java.version = 1.8.0_191
file.separator = /
 
VM Flags:
Non-default VM flags: -XX:CICompilerCount=4 -XX:ConcGCThreads=2 -XX:+DisableExplicitGC -XX:G1HeapRegionSize=1048576 -XX:InitialHeapSize=536870912 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ManagementServer -XX:MarkStackSize=4194304 -XX:MaxGCPauseMillis=20 -XX:MaxHeapSize=536870912 -XX:MaxNewSize=321912832 -XX:MinHeapDeltaBytes=1048576 -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseG1GC 
Command line:  -Xmx512M -Xms512M -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+DisableExplicitGC -Djava.awt.headless=true -Xloggc:/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../logs/zookeeper-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/koushengrui/app/kafka_2.11-0.10.2.0/bin/../logs -Dlog4j.configuration=file:./../config/log4j.properties

jmap:Java堆内存映射工具

[root@centos4 bin]# jmap 
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 -heap pid:打印堆信息。从中可以看出使用的垃圾收集器、堆的配置及其使用情况。如下:

[root@centos4 bin]# jmap -heap 1366
Attaching to process ID 1366, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12

using thread-local object allocation.
Garbage-First (G1) GC with 8 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 536870912 (512.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 321912832 (307.0MB)
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 21807104 (20.796875MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 1048576 (1.0MB)

Heap Usage:
G1 Heap:
   regions  = 512
   capacity = 536870912 (512.0MB)
   used     = 1856512 (1.7705078125MB)
   free     = 535014400 (510.2294921875MB)
   0.34580230712890625% used
G1 Young Generation:
Eden Space:
   regions  = 0
   capacity = 28311552 (27.0MB)
   used     = 0 (0.0MB)
   free     = 28311552 (27.0MB)
   0.0% used
Survivor Space:
   regions  = 0
   capacity = 0 (0.0MB)
   used     = 0 (0.0MB)
   free     = 0 (0.0MB)
   0.0% used
G1 Old Generation:
   regions  = 2
   capacity = 508559360 (485.0MB)
   used     = 1856512 (1.7705078125MB)
   free     = 506702848 (483.2294921875MB)
   0.36505315721649484% used

3009 interned Strings occupying 242720 bytes.

如果jdk的版本比较高,可能jmap不支持-heap选项了,要用jhsdb jmap,型如jhsdb jmap --heap --pid 14。如果是在容器中执行,执行时报错"Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for xxx: Operation not permitted",则在进入容器时需要用--privileged,型如docker exec -it --privileged xxx bash。如果还报错,那么再用root用户登录试试,docker exec -it --privileged -u root xxx bash。zgc的展示如下:

root@d10b0fda9a83:/# jhsdb jmap --heap --pid 14
Attaching to process ID 14, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 17-internal+0-adhoc.root.openjdk

using thread-local object allocation.
ZGC with 3 thread(s)

Heap Configuration:
   MinHeapFreeRatio         = 40
   MaxHeapFreeRatio         = 70
   MaxHeapSize              = 1073741824 (1024.0MB)
   NewSize                  = 1363144 (1.2999954223632812MB)
   MaxNewSize               = 17592186044415 MB
   OldSize                  = 5452592 (5.1999969482421875MB)
   NewRatio                 = 2
   SurvivorRatio            = 8
   MetaspaceSize            = 22020096 (21.0MB)
   CompressedClassSpaceSize = 1073741824 (1024.0MB)
   MaxMetaspaceSize         = 17592186044415 MB
   G1HeapRegionSize         = 0 (0.0MB)

Heap Usage:
 ZHeap          used 186M, capacity 1024M, max capacity 1024M

jmap -histo pid:打印堆中的对象信息。jmap -histo:live:打印堆中存活的对象信息。如下:

[root@centos4 bin]# jmap -histo 1366

 num     #instances         #bytes  class name
----------------------------------------------
   1:          6703         509448  [C
   2:           910         452864  [I
   3:          1889         214352  java.lang.Class
   4:           525         207248  [B
   5:          6665         159960  java.lang.String
   6:          2816         110784  [Ljava.lang.Object;
  ........................................................
 725:             1             16  sun.util.resources.LocaleData
 726:             1             16  sun.util.resources.LocaleData$LocaleDataResourceBundleControl
Total         39669        2380888

num是根据bytes由大到小排列的排名。instances表示同一个class name的对象的个数。bytes是同一个class name的对象的总大小。class name是全类名。

jmap -finalizerinfo pid:打印待回收的对象信息。如下:

[root@centos4 bin]# jmap -finalizerinfo 1366
Attaching to process ID 1366, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.191-b12
Number of objects pending for finalization: 0

jmap -dump:<dump-options>:dump堆信息,生成二进制的heap dump文件,俗称堆转储文件。dump是转储的意思。dump文件名可以自定义。如:

[root@centos4 bin]# jmap -dump:format=b,file=zookeeper_201907112135.dump 1366
Dumping heap to /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-1.el7_6.x86_64/bin/zookeeper_201907112135.dump ...
Heap dump file created

heap dump文件怎么用呢?由于heap dump文件是二进制文件,所以不能直接用文本编辑器打开。把heap dump文件从服务器down下来后,常用打开方式有两种:

用VisualVM打开或者用MAT打开。

用VisualVM打开步骤:双击JAVA_HOME/bin目录中的jvisualvm.exe打开Java VisualVM工具,点击左上角打开,装入,文件类型选择堆 Dump,然后选择刚刚的堆转储文件,就打开了。然后在概要处就可以看到基本信息、环境、系统属性以及堆转储上的线程信息,在类处可以看到所有的类以及每个类的实例数以及各类实例大小和占堆空间的比例。

如果dump文件特别大,就需要用MAT打开了。MAT全称是Eclipse Memory Analyzer,是eclipse官方出的一个独立插件。从官网下载好后,解压,直接双击MemoryAnalyzer.exe即可运行,不用依赖eclipse。左上角File,Open Heap Dump,选择刚刚的堆转储文件,打开。在Overview中可以看到有Actions、Reports、Step By Step,Actions下面有Histogram(列出了各类实例数量及占用内存大小)、Dominator Tree(列出了最大的对象)、Top Consumers(根据类名和包名分组,打印出最昂贵的对象)。Reports下面有Leak Suspects(列出了可能的内存泄露点)。

jstack:java堆栈跟踪工具

[root@centos4 bin]# jstack
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

jstack pid:dump运行的进程的线程信息。如果进程hung住了,需要加-F参数来强制dump。jstack -F pid:dump hung住进程的线程信息。这两个命令都默认把信息输出到当前命令行,我们一般都会输出到指定文件,jstack pid > thread201907121424.dump。这样就会在当前目录中生成thread201907121424.dump文件。down下来分析即可。dump线程生成的文件一般称为线程转储文件。线程转储文件可以直接用文本编辑器如notepad++打开,打开后可以看到dump瞬间所有的线程及其状态。由此可知,当我们自己创建线程或者线程池时,给线程命名是多么好的习惯啊,可以快速在大量的线程中找到自己命名的线程。从中还可以看到大量的Unsafe、LockSupport、AQS、CountDownLatch的API,所以学好这些类是必需的。

posted on 2016-03-16 15:38  koushr  阅读(380)  评论(0编辑  收藏  举报

导航