java線上問題定位工具

原文鏈接:https://www.cnblogs.com/dongguacai/p/5910134.html

在JDK的bin目錄下有很多命令行工具:

             

  我們可以看到各個工具的體積基本上都穩定在27kb左右,這個不是JDK開發團隊刻意爲之的,而是因爲這些工具大多數是jdk\lib\tools.jar類庫的一層薄包裝而已,他們的主要功能代碼是在tools類庫中實現的。命令行工具的好處是:當應用程序部署到生產環境後,無論是直接接觸物理服務器還是遠程telnet到服務器上都會受到限制。而藉助tools.jar類庫裏面的接口,我們可以直接在應用程序中實現功能強大的監控分析功能。

常用命令:

這裏主要介紹如下幾個工具:

1、jps:查看本機java進程信息。

2、jstack:打印線程的信息,製作線程dump文件。

3、jmap:打印內存映射,製作dump文件

4、jstat:性能監控工具

5、jhat:內存分析工具

6、jconsole:簡易的可視化控制檯

7、jvisualvm:功能強大的控制檯

JAVA Dump:

JAVA Dump就是虛擬機運行時的快照,將虛擬機運行時的狀態和信息保存到文件中:

線程dump:包含所有線程的運行狀態,純文本格式

堆dump:包含所有堆對象的狀態,二進制格式

1、jps

顯示當前所有java進程pid的命令,我們可以通過這個命令來查看到底啓動了幾個java進程(因爲每一個java程序都會獨佔一個java虛擬機實例),不過jps有個缺點是隻能顯示當前用戶的進程id,要顯示其他用戶的還只能用linux的ps命令。

執行jps命令,會列出所有正在運行的java進程,其中jps命令也是一個java程序,前面的數字就是對應的進程id,這個id的作用非常大,後面會有相關介紹。

jps -help:

jps -l 輸出應用程序main.class的完整package名或者應用程序jar文件完整路徑名

jps -v 輸出傳遞給JVM的參數

jps失效

我們在定位問題過程會遇到這樣一種情況,用jps查看不到進程id,用ps -ef | grep java卻能看到啓動的java進程。

要解釋這種現象,先來了解下jps的實現機制:

java程序啓動後,會在目錄/tmp/hsperfdata_{userName}/下生成幾個文件,文件名就是java進程的pid,因此jps列出進程id就是把這個目錄下的文件名列一下而已,至於系統參數,則是讀取文件中的內容。

我們來思考下:如果由於磁盤滿了,無法創建這些文件,或者用戶對這些文件沒有讀的權限。又或者因爲某種原因這些文件或者目錄被清除,出現以上這些情況,就會導致jps命令失效。

如果jps命令失效,而我們又要獲取pid,還可以使用以下兩種方法:

1、top | grep java

2、ps -ef |grep java

2、jstack

主要用於生成指定進程當前時刻的線程快照,線程快照是當前java虛擬機每一條線程正在執行的方法堆棧的集合,生成線程快照的主要目的是用於定位線程出現長時間停頓的原因,如線程間死鎖、死循環、請求外部資源導致長時間等待。

3、jmap

主要用於打印指定java進程的共享對象內存映射或堆內存細節。

堆Dump是反映堆使用情況的內存鏡像,其中主要包括系統信息、虛擬機屬性、完整的線程Dump、所有類和對象的狀態等。一般在內存不足,GC異常等情況下,我們會去懷疑內存泄漏,這個時候就會去打印堆Dump。

jmap的用法摘要:

1、jmap pid

打印的信息分別爲:共享對象的起始地址、映射大小、共享對象路徑的全程。

2、jmap -heap pid:查看堆使用情況

 

3、jmap -histo pid:查看堆中對象數量和大小

打印的信息分別是:序列號、Class實例的數量、內存的佔用、類限定名

如果是內部類,類名的開頭會加上*,如果加上live子參數的話,如jmap -histo:live pid,這個命名會觸發一次FUll GC,只統計存活對象

 

4、jmap -dump:format=b,file=heapdump pid:將內存使用的詳細情況輸出到文件

     然後使用jhat命令查看該文件:jhat -port 4000 文件名 ,在瀏覽器中訪問http:localhost:4000/

總結:

該命令適用的場景是程序內存不足或者GC頻繁,這時候很可能是內存泄漏。通過以上命令查看堆使用情況、大量對象被持續引用等情況。

4、jstat

主要是對java應用程序的資源和性能進行實時的命令行監控,包括了對heap size和垃圾回收狀況的監控。

 jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]

option:我們經常使用的選項有gc、gcutil

vmid:java進程id

interval:間隔時間,單位爲毫秒

count:打印次數

1、jstat -gc PID 5000 20

S0C:年輕代第一個survivor的容量(字節)

S1C:年輕代第二個survivor的容量(字節)

S0U:年輕代第一個survivor已使用的容量(字節)

S1U:年輕代第二個survivor已使用的容量(字節)

EC:年輕代中Eden的空間(字節)

EU:年代代中Eden已使用的空間(字節)

OC:老年代的容量(字節)

OU:老年代中已使用的空間(字節)

PC:永久代的容量

PU:永久代已使用的容量

YGC:從應用程序啓動到採樣時年輕代中GC的次數

YGCT:從應用程序啓動到採樣時年輕代中GC所使用的時間(單位:S)

FGC:從應用程序啓動到採樣時老年代中GC(FULL GC)的次數

FGCT:從應用程序啓動到採樣時老年代中GC所使用的時間(單位:S)

2、jstat -gcutil PID 5000 20

s0:年輕代中第一個survivor已使用的佔當前容量百分比

s1:年輕代中第二個survivor已使用的佔當前容量百分比

E:年輕代中Eden已使用的佔當前容量百分比

O:老年代中已使用的佔當前容量百分比

P:永久代中已使用的佔當前容量百分比

5、jhat

主要用來解析java堆dump並啓動一個web服務器,然後就可以在瀏覽器中查看堆的dump文件了。

生成dump文件的方法前面已經介紹了,這邊主要介紹如何解析java堆轉儲文件,並啓動一個web server

jhat heapdump

這個命令將heapdump文件轉換成html格式,並且啓動一個http服務,默認端口爲7000。

如果端口衝突,可以使用以下命令指定端口:jhat -port 4000 heapdump

下面我們來訪問下:ip:port

6、jinfo

jinfo可以用來查看正在運行的java運用程序的擴展參數,甚至支持在運行時動態地更改部分參數。

基本使用語法如下: jinfo -< option > < pid > ,其中option可以爲以下信息:

-flag< name >: 打印指定java虛擬機的參數值

-flag [+|-]< name >:設置或取消指定java虛擬機參數的布爾值

-flag < name >=< value >:設置指定java虛擬機的參數的值

使用示例

下面的命令顯示了新生代對象晉升到老年代對象的最大年齡。在運行程序運行時並沒有指定這個參數,但是通過jinfo,可以查看這個參數的當前的值。

下面的命令顯示是否打印gc詳細信息:

下面的命令在運用程序運行時動態打開打印詳細gc信息開關:

注意事項:jinfo雖然可以在java程序運行時動態地修改虛擬機參數,但並不是所有的參數都支持動態修改。

7、jcmd

在JDK 1.7之後,新增了一個命令行工具jcmd。它是一個多功能工具,可以用來導出堆,查看java進程,導出線程信息,執行GC等。jcmd擁有jmap的大部分功能,Oracle官方建議使用jcmd代替jmap。

使用 jcmd -l 命令列出當前運行的所有虛擬機,示例:

針對每一個虛擬機,可以使用help命令列出該虛擬機支持的所有命令,示例:

其中,

  • VM.native_memory
  • VM.commercial_features
  • GC.rotate_log
  • ManagementAgent.stop
  • ManagementAgent.start_local
  • ManagementAgent.start
  • Thread.print,                         打印線程棧信息
  • GC.class_histogram,              查看系統中類統計信息
  • GC.heap_dump,                    導出堆信息,與jmap -dump功能一樣
  • GC.run_finalization,               觸發finalize()
  • GC.run,                                觸發gc()
  • VM.uptime,                           VM啓動時間
  • VM.flags,                              獲取JVM啓動參數
  • VM.system_properties,          獲取系統Properties
  • VM.command_line,                 啓動時命令行指定的參數
  • VM.version
  • help

示例:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章