JDK自帶命令行工具詳解

Content

Top

1. 背景

給一個系統定位問題的時候,知識、經驗是關鍵基礎,數據(運行日誌、異常堆棧、GC日誌、線程快照[threaddump / javacore文件]、堆轉儲快照[heapdump / hprof])是依據,工具是運用知識處理數據的手段。

經常使用適當的虛擬機監控和分析的工具可以加快我們分析數據、定位解決問題的速度。

Top

2. jps

jps(JVM Process Status Tool)可以列出正在運行的虛擬機進程,並顯示虛擬機執行主類(Main Class,main()函數所在的類)名稱以及這些進程的本地虛擬機唯一ID(Local Virtual Machine Identifier,LVMID)。對於本地虛擬機進程來說,LVMID與操作系統的進程ID(Process Identifier, PID)是一致的。

2.1 用法

主要選項

選項 作用 備註
-q 只輸出LVMID,省略主類的名稱  
-m 輸出虛擬機進程啓動時傳遞給主類main()函數的參數  
-l 輸出主類的全名,如果進程執行的是jar包,輸出jar路徑  
-v 輸出虛擬機進程啓動時JVM參數  

Top

3. jstat

3.1 用法

 jstat(JVM Statistics Monitoring Tool)是用於監視虛擬機各種運行狀態信息的命令行工具。

它可以顯示本地或遠程虛擬機進程中的類裝載、內存、垃圾收集、JIT編譯等運行數據。

 jstat [option vmid [interval][s|ms] [count]]

option代表用戶希望查詢的虛擬機信息,主要分爲3類:類裝載、垃圾收集、運行期編譯狀況。具體如下表:

 

選項 作用
-class

監視類裝載、卸載數量、總空間以及類裝載所耗費的時間。

Loaded:加載class的數量;

Bytes:所佔用空間大小;

Unloaded:未加載數量;

Bytes:未加載佔用空間;

Time:加載耗時。

-gc

 監視Java堆狀況,包括Eden區、兩個Survivor區、老年區、元數據等的容量、已用空間,GC時間合計等信息。

S0C,S1C,EC,OC,MC,CCSC:S0,S1,Eden,老年代,Metaspace和壓縮類空間大小;

S0U,S1U,EU,OU,MU,CCSU:S0,S1,Eden,老年代,Metaspace和壓縮類空間已經使用的大小;

YGC,YGCT,FGC,FGCT:Young GC和Full GC的次數和耗時;

GCT:垃圾回收的耗時。

-gccapacity

 監視內容與-gc基本相同,但輸出主要關注Java堆各個區域使用到的最大、最小空間。

NGCMN,NGCMX,NGC:新生代最小、最大和當前容量;

S0C,S1C,EC:s0,s1,eden區大小;

OGCMN,OGCMX,OGC:老年代最小、最大和當前容量;

OC:老年代當前容量;

MCMN,MCMX,MC:元數據最小、最大和當前容量;

CCSMN,CCSMX,CCSC:壓縮類空間的最小、最大和當前容量;

YGC,FGC:minor GC和full GC的次數。

-gcutil

 監視內容與-gc基本相同,但輸出主要關注已使用空間佔總空間的百分比。

S0,S1(標示Survivor0,Survivor1):使用了0%;

E(新生代Eden區):使用了5.78%;

O(老年代):使用了16.92%;

M(元空間Metaspace):使用了91.97%;

CCS:壓縮使用81.54%;

YGC(標示Young GC),YGCT:程序運行以來共發生Minor GC651次,總耗時4.446秒;

FGC(標示Full GC),FGCT:Full GC640次,總耗時86.409秒;

GCT(GC Time):所有GC耗時爲90.855。

-gccause

 與-gcutil功能一樣,但是會額外輸出導致上一次GC產生的原因。

-gcnew

 監視新生代GC狀況。

S0C,S1C,S0U,S1U,EC,EU,YGC,YGCT同上;

TT:對象在新生代存活的次數;

MTT:對象在新生代存活的最大次數;

-gcnewcapacity

 監視內容與-gcnew基本相同,輸出主要關注使用到的最大、最小空間。

同上

-gcold

 監視老年代GC狀況。

-gcoldcapacity

 監視內容與-gcold基本相同,輸出主要關注使用到的最大、最小空間。

-gcmetacapacity

 輸出元數據(Metaspace)使用到的最大、最小空間。

 

 

 

 

-compiler

 輸出JIT編譯器編譯過的方法、耗時等信息。

Compiled:編譯方法數量;

Failed:失敗數量;

Invalid:不可用數量;

Time:編譯耗時;

FailedType:失敗類型;

FailedMethod:失敗的方法。

-printcompilation

 輸出已經被JIT編譯的方法。

Compiled:最近編譯方法的數量;

Size:最近編譯方法的字節碼數量;

Type:最近編譯方法的編譯類型;

Method:方法名標識。

   

如果是本地虛擬機進程,則VMID與LVMID是一致的,如果是遠程虛擬機進程,那麼VMID的格式是:

[protocal:][//]vmid[@hostname[:port]/servername]

interval代表查詢間隔

count代表查詢次數

如果省略這兩個參數,說明只查詢一次。

Top

4. jinfo(即將廢棄)

jinfo(Configuration Info for Java)的作用是實時地查看和調整虛擬機各項參數。

使用jps -v命令可以查看虛擬機啓動時顯式指定的參數列表,但如果想知道未被顯式指定的參數的系統默認值。

可以使用jinfo的-flag選項進行查詢

4.2 用法

 jinfo [option] pid

Top

5. jmap

jmap(Memory Map for Java,Java內存映像工具):命令用於生成堆轉儲快照(heapdump或dump文件)。

-XX:+HeapDumpOnOutOfMemoryError參數,可以讓虛擬機在OOM異常出現之後自動生成dump文件,

通過-XX:+HeapDumpOnCtrlBreak參數則可以使用Ctrl + Break組合鍵讓虛擬機生成dump文件。

 jmap還可以查詢finalize執行隊列,Java堆和永久代的詳細信息,如空間使用率,當前用的是哪種收集器等。

說明:除了生成dump文件的-dump選項和用於查看每個類的實例、空間佔用統計的-histo選項在所有操作系統都提供之外,其餘選項都只能在Linux / Solaris使用。

5. 2 用法

jmap [option] vmid

option選項的合法值與具體含義如下表:

選項 作用
-dump

生成Java堆轉儲快照,格式爲:-dump[live, ]format=b, file=<filename>,其中live子參數說明是否只dump出存活的對象。

如: jmap -dump:format=b,file=dump.bin 3500

-finalizerinfo 顯示在F-Queue中等待Finalizer線程執行finalize方法的對象。只在Linux/Solaris平臺下有效。
-heap 顯示Java堆詳細信息,如使用哪種回收器,參數配置,分代狀況等。只在Linux/Solaris平臺下有效。
-histo 顯示堆中對象統計信息,包括類,實例數量,合計容量。
-permstat 以ClassLoader爲統計口徑顯示永久代內存狀況,只在Linux/Solaris平臺有效。
-F 當虛擬機進程堆-dump選項沒有響應時,可使用這個選項強制生成dump快照。只在Linux/Solaris平臺有效。

注意:更爲詳細的使用可以參考:Java內存分析工具jmap

Top

6. jhat 

jhat虛擬機堆轉儲快照分析工具,用來分析jmap生成的堆轉儲快照。

jhat內置了一個微型的HTTP/HTML服務器 ,生成dump文件的分析結果後,可以在瀏覽器中查看。

一般不會直接使用jhat,而是採用更加專業的VisualVM,Eclipse Memory Analyzer,IBM HeapAnalyzer等。

6.1 用法

jhat dump.bin

Top

7. jstack

jstack(Stack Trace for Java):用來生成虛擬機當前時刻的線程快照(稱爲threaddump或javacore文件)。

線程快照就是當前虛擬機內每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致的長時間等待等都是導致線程長時間停頓的常見原因。線程出現停頓的時候通過jstack來查看各個線程的調用堆棧,就可以知道沒有響應的線程到底是後臺做什麼請求,或等待什麼資源。

7.1 用法

jstack [option] vmid

option選項的合法值如下表:

選項 作用
-F 當正常輸出的請求不被響應時,強制輸出線程堆棧
-l 除堆棧外,顯示關於鎖的附加信息
-m 如果調用到本地方法的話,可以顯示C/C++的堆棧

Top

8. javap

javap是JDK自帶的反彙編器,可以查看java編譯器爲我們生成的字節碼。通過它,我們可以對照源代碼和字節碼,從而瞭解很多編譯器內部的工作。

8.2 用法

語法:
  javap [ 命令選項 ] class. . .
  javap命令用於解析類文件。其輸出取決於所用的命令選項。若沒有使用命令選項,javap將輸出傳遞給它的類的public 域及方法。javap將其輸出到標準輸出設備上。
命令選項:
  -help 輸出 javap 的幫助信息。
  -l 輸出行及局部變量表。
  -b 確保與 JDK 1.1 javap 的向後兼容性。
  -public 只顯示 public 類及成員。
  -protected 只顯示 protected 和 public 類及成員。
  -package 只顯示包、protected 和 public 類及成員。這是缺省設置。
  -private 顯示所有類和成員。
  -J[flag] 直接將 flag 傳給運行時系統。
  -s 輸出內部類型簽名。
  -c 輸出類中各方法的未解析的代碼,即構成 Java 字節碼的指令。
  -verbose 輸出堆棧大小、各方法的 locals 及 args 數,以及class文件的編譯版本
  -classpath[路徑] 指定 javap 用來查找類的路徑。如果設置了該選項,則它將覆蓋缺省值或 CLASSPATH 環境變量。目錄用冒號分隔。
    -bootclasspath[路徑] 指定加載自舉類所用的路徑。缺省情況下,自舉類是實現核心 Java 平臺的類,位於 jrelib下面。

       -extdirs[dirs] 覆蓋搜索安裝方式擴展的位置。擴展的缺省位置是 jrelibext。

8.3 實例

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

package com.huawei.thread;

 

public class Test44 {

    public static volatile int race = 0;

 

    public static void increase() {

        race++;

    }

 

    private static final int THREADS_COUNT = 20;

 

    public static void main(String[] args) {

        Thread[] threads = new Thread[THREADS_COUNT];

        for (int i = 0; i < THREADS_COUNT; i++) {

            threads[i] = new Thread(new Runnable() {

 

                @Override

                public void run() {

                    for (int i = 0; i < 10000; i++) {

                        increase();

                    }

                }

            });

            threads[i].start();

        }

        while (Thread.activeCount() > 1) {

            Thread.yield();

        }

        System.out.println(race);

    }

 

}  

javap -c Test44生成的字節碼爲:

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

D:\workspace\Thread\bin\com\huawei\thread>javap -c Test44

警告: 二進制文件Test44包含com.huawei.thread.Test44

Compiled from "Test44.java"

public class com.huawei.thread.Test44 {

  public static volatile int race;

 

  static {};

    Code:

       0: iconst_0

       1: putstatic     #13                 // Field race:I

       4return

 

  public com.huawei.thread.Test44();

    Code:

       0: aload_0

       1: invokespecial #18                 // Method java/lang/Object."<init>":()V

       4return

 

  public static void increase();

    Code:

       0: getstatic     #13                 // Field race:I

       3: iconst_1

       4: iadd

       5: putstatic     #13                 // Field race:I

       8return

 

  public static void main(java.lang.String[]);

    Code:

       0: bipush        20

       2: anewarray     #25                 // class java/lang/Thread

       5: astore_1

       6: iconst_0

       7: istore_2

       8goto          37

      11: aload_1

      12: iload_2

      13new           #25                 // class java/lang/Thread

      16: dup

      17new           #27                 // class com/huawei/thread/Test44$1

      20: dup

      21: invokespecial #29                 // Method com/huawei/thread/Test44$1."<init>":()V

      24: invokespecial #30                 // Method java/lang/Thread."<init>":(Ljava/lang/Runnable;)V

      27: aastore

      28: aload_1

      29: iload_2

      30: aaload

      31: invokevirtual #33                 // Method java/lang/Thread.start:()V<br>

      34: iinc          21

      37: iload_2

      38: bipush        20

      40: if_icmplt     11

      43goto          49

      46: invokestatic  #36                 // Method java/lang/Thread.yield:()V

      49: invokestatic  #39                 // Method java/lang/Thread.activeCount:()I

      52: iconst_1

      53: if_icmpgt     46

      56: getstatic     #43                 // Field java/lang/System.out:Ljava/io/PrintStream;

      59: getstatic     #13                 // Field race:I

      62: invokevirtual #49                 // Method java/io/PrintStream.println:(I)V

      65return

發佈了58 篇原創文章 · 獲贊 17 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章