1. 程式人生 > >JVM除錯常用命令——jps、(1)

JVM除錯常用命令——jps、(1)

本篇文章根據作者最近一段時間的工作經歷和閱讀網路資料進而完成的總結。主要對JVM除錯過程中使用的命令進行總結,並列舉了一個在實際工作中出現的JVM除錯場景進行講解。

這裡要說明一下,在線上環境是不存在使用者介面的只有命令列介面,所以我們使用JMX在使用類似jconsole、jvisualvm(包括外掛)這樣的介面化程式進行除錯實不可取的,只能使用多種命令結合的方式進行。

1、常用命令介紹

首先介紹在命令列模式下經常使用的java相關指令,以及它們經常搭配的各種引數,包括:jps、jstat、jinfo、jmap。這些命令中,又數jstat和jmap命令最為重要。

1.1、jps命令

jps命令主要用於檢視有權訪問的hotspot虛擬機器下工作的java程序(預設為本作業系統),以及程序編號。使用方式如下:

usage: jps [-help]
       jps [-q] [-mlvV] [<hostid>]

例如:

# jps
26032
251056 Jps
11640
143420
// 以上是當前作業系統正在於執行的java程序,注意那個“251056”,jps也是一個java程序。

jps可以使用的引數包括:

  • -q :僅僅顯示VM 標示,不顯示jar,class, main引數等資訊.
  • m:輸出當執行java程序主方法時,操作者傳入的引數.
  • l: 輸出應用程式主類完整package名稱或jar完整名稱。例項如下:
# jps -l
26032
248736 org.eclipse.jdt.internal.junit.runner.RemoteTestRunner
11640
143420
247660 sun.tools.jps.Jps
  • v: 列出jvm引數, 例如-Xms100m -Xmx500m……,使用示例如下:
 # jps -v
26032  -Dosgi.requiredJavaVersion=1.8 -XX:+UseG1GC -XX:+UseStringDeduplication -Dosgi.requiredJavaVersion=
1.8 -Xms256m -Xmx1024m 248736 RemoteTestRunner -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:63591 -ea -Dfile.encoding=UTF-8 264176 Jps -Denv.class.path=D:\Program Files\Java\jdk1.8.0_144\ -Dapplication.home=D:\Program Files\Java\jdk1.8.0_144 -Xms8m 143420 -Dosgi.requiredJavaVersion=1.8 -Xms4G -Dosgi.module.lock.timeout=10 -Xverify:none -Dorg.eclipse.swt.browser.IEVersion=10001 -Xmx4G -javaagent:lombok.jar
  • -V 輸出通過.hotsportrc或-XX:Flags=指定的jvm引數

1.2、jinfo命令

jinfo命令可以用來檢視正在執行的java程序的執行引數和環境引數;在一些特定情況下,還可以在執行時修改部分引數。使用格式如下:

Usage:
    jinfo [option] <pid>
        (to connect to running process)
    jinfo [option] <executable <core>
        (to connect to a core file)
    jinfo [option] [[email protected]]<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 248736
Attaching to process ID 248736, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.144-b01
Java System Properties:

java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.144-b01
java.vendor.url = http://java.oracle.com/
java.vm.vendor = Oracle Corporation
………………………………為了節約篇幅,省略了一些資訊
java.endorsed.dirs = D:\Program Files\Java\jdk1.8.0_144\jre\lib\endorsed
line.separator =

java.io.tmpdir = C:\Users\ADMINI~1\AppData\Local\Temp\
java.vm.specification.vendor = Oracle Corporation
user.variant =
os.name = Windows 10
sun.jnu.encoding = GBK
java.library.path = D:\Program Files\Java\jdk1.8.0_144\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;D:\Program Files\Java\jdk1.8.0_144\jre\bin;D:/Program Files/Java/jdk1.8.0_144/bin/../jre/bin/server;D:/Program Files/Java/jdk1.8.0_144/bin/../jre/bin;D:/Program Files/Java/jdk1.8.0_144/bin/../jre/lib/amd64;C:\Windows\System32;C:\Windows;C:\Windows\System32\wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Java\jdk1.8.0_144\bin\;D:\apache-maven-3.2.3\bin;F:\hadoop-2.6.0-cdh5.4.4\bin;D:\Program Files\Java\jdk1.8.0_144\bin;D:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;;.
………………………………為了節約篇幅,又省略了一些資訊
sun.cpu.endian = little
sun.desktop = windows
sun.cpu.isalist = amd64

VM Flags:
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=264241152 -XX:MaxHeapSize=4213178368 -XX:MaxNewSize=1404043264 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=88080384 -XX:OldSize=176160768 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:63591 -ea -Dfile.encoding=UTF-8

注意,jinfo列印的各種引數分為兩種型別,一種叫做系統環境引數,另一種叫做JVM引數(後面會講到)。 以上示例中,那個“248736”引數就是指定的java程序的程序號,可以通過多種方式獲得,例如通過jps命令。那麼下面我們詳細介紹一下jinfo命令的主要引數:

  • flags
    使用該命令引數,列印當前指定java程序中已經設定的所有JVM引數資訊。使用方式類似如下(注意,以下示例方式中的“314360”是java程序號):
# jinfo -flags 314360
Attaching to process ID 314360, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.144-b01
Non-default VM flags: -XX:CICompilerCount=4 -XX:InitialHeapSize=264241152 -XX:MaxHeapSize=4213178368 -XX:MaxNewSize=1404043264 -XX:MinHeapDeltaBytes=524288 -XX:NewSize=88080384 -XX:OldSize=176160768 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:-UseLargePagesIndividualAllocation -XX:+UseParallelGC
Command line:  -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:55792 -ea -Dfile.encoding=UTF-8
  • -flag <name>
    使用該命令引數,可以打印出指定的引數資訊,使用方式類似如下:
// 只顯示當前指定程序中-XX:MinHeapDeltaBytes引數的值
# jinfo -flag MinHeapDeltaBytes 314360
-XX:MinHeapDeltaBytes=524288

// 再來一個,只顯示當前指定程序中-XX:MaxNewSize引數的設定值
# jinfo -flag MaxNewSize 314360
-XX:MaxNewSize=1404043264
  • -sysprops
    使用該命令引數,列印當前java程序中設定的系統環境引數。使用方式如下(注意,以下示例方式中的“314360”也是java程序號):
# jinfo -sysprops  314360
Attaching to process ID 314360, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.144-b01
java.runtime.name = Java(TM) SE Runtime Environment
java.vm.version = 25.144-b01
………………………………為了節約篇幅,又省略了一些資訊
sun.cpu.endian = little
sun.desktop = windows
sun.cpu.isalist = amd64
  • -flag [+|-] <name>
    通過該命令引數,可以更改標記型別為“manageable”,且設定值為“bool”型的引數值,使用示例如下:
// 這個“XX:+PrintGC”引數設定值為“bool”型,所以可以通過這個引數向java程序增加設定資訊
# jinfo -flag +PrintGC 314360

// 還可以通過類似命令,從當前java程序中減少相關的JVM引數
# jinfo -flag -PrintGC 314360
  • -flag <name>=<value>
    通過該命令引數,可以為一些JVM引數設定新的值,使用示例如下:
# jinfo -flag CMSWaitDuration=3000 314360

// 當我們再通過-flags命令引數檢視時,就可以看到這個設定了,如下:
Attaching to process ID 314360, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.144-b01
Non-default VM flags: -XX:CICompilerCount=4 -XX:CMSWaitDuration=3000 ……………………
………………

上文提到了,jinfo命令可以修改一部分java程序引數,那麼哪些引數可以修改呢?可以通過以下命令來確認

// windows 方式
# java -XX:+PrintFlagsFinal -version | findstr /i  manageable
// Linux 方式
# java -XX:+PrintFlagsFinal -version | grep manageable

// 將列出的資訊類似如下:
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)
     intx CMSAbortablePrecleanWaitMillis            = 100                                 {manageable}
     intx CMSTriggerInterval                        = -1                                  {manageable}
     intx CMSWaitDuration                           = 2000                                {manageable}
     bool HeapDumpAfterFullGC                       = false                               {manageable}
     bool HeapDumpBeforeFullGC                      = false                               {manageable}
     bool HeapDumpOnOutOfMemoryError                = false                               {manageable}
    ccstr HeapDumpPath                              =                                     {manageable}
    uintx MaxHeapFreeRatio                          = 100                                 {manageable}
    uintx MinHeapFreeRatio                          = 0                                   {manageable}
     bool PrintClassHistogram                       = false                               {manageable}
     bool PrintClassHistogramAfterFullGC            = false                               {manageable}
     bool PrintClassHistogramBeforeFullGC           = false                               {manageable}
     bool PrintConcurrentLocks                      = false                               {manageable}
     bool PrintGC                                   = false                               {manageable}
     bool PrintGCDateStamps                         = false                               {manageable}
     bool PrintGCDetails                            = false                               {manageable}
     bool PrintGCID                                 = false                               {manageable}
     bool PrintGCTimeStamps                         = false                               {manageable}

注意,實際上“java -XX:+PrintFlagsFinal -version”命令可以找到所有的flag資訊,但是我們只能對標記為“manageable”的flag資訊進行修改。

============
(接下文)