Jvm dump jstack jmap jstat 介紹與使用(內存與線程) 以及使用jstack定位問題


這個問題阿里經常問,參考:阿里面試 

結論:

(1)棧信息:jstack <pid>輸出的信息

(2)堆信息:jmap -dump <pid>輸出的文件

(3)jstat查看gc情況,jstat -gc  <PID> 間隔毫秒數 比如  jstat -gc 12345 5000  也就是每隔5秒打印進程12345的 gc情況

 

一、看一下 jstack

jstack -m <pid> >jvm_deadlocks.txt   jstack -l <pid> >jvm_listlocks.txt   參考資料 jstack - Stack Trace

使用top -H -p <pid>找出某進程中要分析的線程ID,然后將線程ID轉換為16進制后,在線程dump文件中搜索相關信息

首先看一下我自己在項目中使用 jstack如何查詢問題:

可以使用jstat查看 gc情況  jstat -gc  12345  5000 (jstat -gc 進程號  間隔毫秒數)

定位問題

(1) 首先 找到相應的進程 使用 ps -ef | grep 'com.sankuai.qcs.regulation.dispatch'

找到進程的ID;==>21980

(2) top -Hp 21980(查詢耗時最高的線程),發現有個線程確實不正常;

(3)jstack 21980 |grep '線程的16進制的ID'

注意 在第二步查到線程的ID之后,轉換成16進制的。放在(3)里面; 

同事查的:

進入系統 使用 grep -n 'java.lang.Thread.State:BLOCKED' jstack.log -A5;

查詢: 

 

Java通過jvm自己管理內存,同時Java提供了一些命令行工具,用於查看內存使用情況。
這里主要介紹一下jstat、jmap命令以及相關工具。 

很多情況下,都會出現dump這個字眼,java虛擬機jvm中也不例外,其中主要包括內存dump、線程dump。 

當發現應用內存溢出或長時間使用內存很高的情況下,通過內存dump進行分析可找到原因。

當發現cpu使用率很高時,通過線程dump定位具體哪個線程在做哪個工作占用了過多的資源。 

首先,內存dump是指通過jmap -dump <pid>輸出的文件,而線程dump是指通過jstack <pid>輸出的信息

兩個dump可以單獨使用,也可以在特定場合下結合使用。 

在linux操作系統下(已安裝jdk),執行jps命令,列出正在運行的java程序的進程ID。

 

使用top查看目前正在運行的進程使用系統資源情況。

 

其中進程號為24660的進程,jps輸出列表和top列表中都出現,並且在top列表中顯示是由java COMMAND啟動的。

其中%MEM為2.9,說明占用系統內存為2.9%,當前系統大概8G內存;另外%CPU指的是當前進程使用CPU資源百分比;

 

二、看一下jmap:

使用  jmap -heap pid ,可以查看各個代的內存使用情況。
 jmap -heap 2083

  可以觀察到New Generation(Eden Space,From Space,To Space),tenured generation,Perm Generation的內存使用情況 

 jmap -dump:format=b,file=heapdump.hprof <pid>
  導出heap dump到文件heapdump.hprof
 
 jmap -histo 2083 | jmap -histo:live 2083

 可以觀察heap中所有對象的情況(heap中所有生存的對象的情況)。包括對象數量和所占空間大小。 

jmap輸出的 class name結果中:
[C is a char[]
[S is a short[] [I is a int[] [B is a byte[] [[I is a int[][] 
 
heap輸出實例
$ jmap -heap 12264
JVM version is 25.65-b01

using parallel threads in the new generation. using thread-local object allocation. Concurrent Mark-Sweep GC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize = 8388608000 (8000.0MB) NewSize = 2006515712 (1913.5625MB) MaxNewSize = 2006515712 (1913.5625MB) OldSize = 90636288 (86.4375MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: New Generation (Eden + 1 Survivor Space): capacity = 1805910016 (1722.25MB) used = 788045040 (751.5383148193359MB) free = 1017864976 (970.7116851806641MB) 43.637004779755316% used Eden Space: capacity = 1605304320 (1530.9375MB) used = 630378472 (601.1757583618164MB) free = 974925848 (929.7617416381836MB) 39.26847166274367% used From Space: capacity = 200605696 (191.3125MB) used = 157666568 (150.36255645751953MB) free = 42939128 (40.94994354248047MB) 78.59525982751757% used To Space: capacity = 200605696 (191.3125MB) used = 0 (0.0MB) free = 200605696 (191.3125MB) 0.0% used concurrent mark-sweep generation: capacity = 6382092288 (6086.4375MB) used = 4612472232 (4398.79630279541MB) free = 1769620056 (1687.6411972045898MB) 72.27210174745753% used 18841 interned Strings occupying 1633048 bytes. 
 

【內存dump】

jmap –dump:live,format=b,file=heap.bin <pid>

參考資料:jmap - Memory Map 

將生成的heap.bin文件,使用ha456.jar工具打開分析。java -jar -Xmx3000m ha456.jar

三、jstat查看 gc實時執行情況

jstat命令命令格式:
jstat [Options] vmid [interval] [count]
 
命令參數說明:
Options,一般使用 -gcutil 或  -gc 查看gc 情況
pid,當前運行的 java進程號 
interval,間隔時間,單位為秒或者毫秒 
count,打印次數,如果缺省則打印無數次
 
Options 參數如下:
-gc:統計 jdk gc時 heap信息,以使用空間字節數表示
-gcutil:統計 gc時, heap情況,以使用空間的百分比表示
-class:統計 class loader行為信息
-compile:統計編譯行為信息
-gccapacity:統計不同 generations(新生代,老年代,持久代)的 heap容量情況
-gccause:統計引起 gc的事件
-gcnew:統計 gc時,新生代的情況
-gcnewcapacity:統計 gc時,新生代 heap容量
-gcold:統計 gc時,老年代的情況
-gcoldcapacity:統計 gc時,老年代 heap容量
-gcpermcapacity:統計 gc時, permanent區 heap容量
 
示例 
  $ jstat -gc 12538 5000
每5 秒一次顯示進程號為 12538的 java進程的 GC情況,結果如下圖:
 
 
結果說明
標志
說明
S0C
年輕代中第一個survivor區的容量 (字節)
S1C
年輕代中第二個survivor區的容量 (字節)
S0U
年輕代中第一個survivor區目前已使用空間 (字節)
S1U
年輕代中第二個survivor區目前已使用空間 (字節)
EC
年輕代中Eden的容量 (字節)
EU
年輕代中Eden目前已使用空間 (字節)
OC
Old代的容量 (字節)
OU
Old代目前已使用空間 (字節)
PC
Perm(持久代)的容量 (字節)
PU
Perm(持久代)目前已使用空間 (字節)
YGC
從應用程序啟動到采樣時年輕代中gc次數
YGCT
從應用程序啟動到采樣時年輕代中gc所用時間(s)
FGC
從應用程序啟動到采樣時old代(全gc)gc次數
FGCT
從應用程序啟動到采樣時old代(全gc)gc所用時間(s)
GCT
從應用程序啟動到采樣時gc用的總時間(s)
NGCMN
年輕代(young)中初始化(最小)的大小 (字節)
NGCMX
年輕代(young)的最大容量 (字節)
NGC
年輕代(young)中當前的容量 (字節)
OGCMN
old代中初始化(最小)的大小 (字節)
OGCMX
old代的最大容量 (字節)
OGC
old代當前新生成的容量 (字節)
PGCMN
perm代中初始化(最小)的大小 (字節)
PGCMX
perm代的最大容量 (字節)  
PGC
perm代當前新生成的容量 (字節)
S0
年輕代中第一個survivor區已使用的占當前容量百分比
S1
年輕代中第二個survivor區已使用的占當前容量百分比
E
年輕代中Eden已使用的占當前容量百分比
O
old代已使用的占當前容量百分比
P
perm代已使用的占當前容量百分比
S0CMX
年輕代中第一個survivor區的最大容量 (字節)
S1CMX
年輕代中第二個survivor區的最大容量 (字節)
ECMX
年輕代中Eden的最大容量 (字節)
DSS
當前需要survivor區的容量 (字節)(Eden區已滿)
TT
持有次數限制
MTT
最大持有次數限制
 
 
jstatd 啟動jvm 監控服務
它是一個基於 rmi的應用,向遠程機器提供本機 jvm應用程序的信息。默認端口 1099。
  $ jstatd -J-Djava.security.policy=my.policy
 
my.policy文件需要自己建立,是安全策略文件,因為 jdk對 jvm做了 jaas的安全檢測,所以我們必須設置一些策略,使 jstatd被允許作網絡操作,內容如下:
grant codebase " file:$JAVA_HOME/lib/tools.jar " {
    permission java.security.AllPermission;
};
 
 
二、jmap查看各個代的內存使用
jmap 可以從 core文件或進程中獲得內存的具體匹配情況,包括 Heap size, Perm size等等。
 
jmap命令格式:
     jmap [ option ] <pid> | <executable core> | <[server-id@]remote-hostname-or-IP>
 
1)參數說明  
pid:java進程 id
executable:產生 core dump的 java可執行程序
core:core dump文件
remote-hostname-or-IP:遠程 debug服務的主機名或 ip
server-id:遠程 debug服務的 id  
2) option參數:
-heap 
打印heap的概要信息,GC 使用的算法,heap的配置及使用情況 . 
-histo[:live] 
打印jvm heap 的直方圖。輸出類名、每個類的實例數目、對象占用大小。 VM的內部類名字開頭會加上前綴 ”*”. 
如果加上live 則只統計活的對象數量。 
-dump:[live,]format=b,file=<filename> 
使用hprof二進制形式,導出heap 內容到文件filename。
假如指定live 選項,那么只輸出活的對象到文件 .  
-finalizerinfo 
打印正等候回收的對象的信息 .
 
-permstat 
打印classload 和jvm heap 持久代的信息。
包含每個classloader 的名字、是否存活、地址、父 classloade、加載的 class數量、內部 String的數量和占用內存數。
 
-F
當pid沒有響應的時候,與-dump或者 -histo共同使用,強制生成 dump文件或 histo信息 . 在這個模式下 ,live子參數無效 . 
 
-J
傳遞參數給啟動jmap 的jvm.
64位機上使用需要使用如下方式: jmap -J-d64 -heap pid
 
jmap 相關工具
  jmap dump生成的 heap dump文件,可以使用 IBM HeapAnalyzer分析工具分析
  下載:
 
  運行:java –Xmx800m –jar ha456.jar 
 
三、jstack和 jinfo分析java core文件
jstack工具可以用來獲得 core文件的 java stack和 native stack的信息,從而可以知道 java程序是如何崩潰和在程序何處發生問題。
另外,jstack 工具還可以附屬到正在運行的 java程序中,看到 java程序的 java stack和native stack 的信息,如果現在運行的 java程序呈現 hung的狀態, jstack是非常有用的。
命令格式:$ jstack pid 
jinfo可以從 core文件里面知道崩潰的 Java應用程序的配置信息。
命令額格式:$ jinfo pid 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM