柚子快報(bào)激活碼778899分享:JVM之jstack命令解析
柚子快報(bào)激活碼778899分享:JVM之jstack命令解析
?命令介紹:
??????? jstack全稱(chēng)叫Java Stack Trace,Java的堆棧跟蹤工具,用于生成java虛擬機(jī)當(dāng)前時(shí)刻的線程快照。功能主要有兩個(gè),1.分析死鎖;2.分析CPU過(guò)高問(wèn)題。
線程快照里留意下面幾種狀態(tài)
死鎖,Deadlock(重點(diǎn)關(guān)注)等待資源,Waiting on condition(重點(diǎn)關(guān)注)等待獲取管程,Waiting on monitor entry(重點(diǎn)關(guān)注) 阻塞,Blocked(重點(diǎn)關(guān)注) 執(zhí)行中,Runnable暫停,Suspended對(duì)象等待中,Object.wait() 或 TIMED_WAITING停止,Parked
Jstack 命令格式如下
jstack [ option ] pid 查看當(dāng)前時(shí)間點(diǎn),指定進(jìn)程的dump堆棧信息。
jstack [ option ] pid > 文件 將當(dāng)前時(shí)間點(diǎn)的指定進(jìn)程的dump堆棧信息,寫(xiě)入到指定文件中。# 注:若該文件不存在,則會(huì)自動(dòng)生成; 若該文件存在,則會(huì)覆蓋源文件。
jstack [ option ] executable core 查看當(dāng)前時(shí)間點(diǎn),core文件的dump堆棧信息。
jstack [ option ] [server_id@]
option 參數(shù)如下:
-F 當(dāng)正常輸出的請(qǐng)求不被響應(yīng)時(shí),強(qiáng)制輸出線程堆棧 -m 打印java和native c/c++框架的所有棧信息??梢源蛴VM的堆棧,以及Native的棧幀,一般應(yīng)用排查不需要使用。 -l 除堆棧外,顯示關(guān)于鎖的附加信息,在發(fā)生死鎖時(shí)可以用jstack -l pid來(lái)觀察鎖持有情況
參數(shù)解釋?zhuān)?/p>
executable: 產(chǎn)生core dump的java可執(zhí)行程序core: 將被打印信息的core dump文件remote-hostname-or-IP: 遠(yuǎn)程debug服務(wù)的主機(jī)名或ipserver-id: 唯一id,假如一臺(tái)主機(jī)上多個(gè)遠(yuǎn)程debug服務(wù)
以下用兩個(gè)實(shí)戰(zhàn)案例來(lái)分析這兩種情況:
實(shí)戰(zhàn)案例1:jstack分析死鎖
案例代碼
public class DeadLockTest {
private static Object lock1 = new Object();
private static Object lock2 = new Object();
public static void main(String[] args) {
new Thread(() -> {
synchronized (lock1) {
try {
System.out.println("thread1 begin");
Thread.sleep(6000);
} catch (InterruptedException e) {
}
synchronized (lock2) {
System.out.println("thread1 end");
}
}
}).start();
new Thread(() -> {
synchronized (lock2) {
try {
System.out.println("thread2 begin");
Thread.sleep(6000);
} catch (InterruptedException e) {
}
synchronized (lock1) {
System.out.println("thread2 end");
}
}
}).start();
System.out.println("main thread end");
}
}
排查命令
jstack 進(jìn)程ID
或
jstack 進(jìn)程ID| grep 'BLOCKED' -A 15 --color
結(jié)果分析:
??????? 通過(guò)結(jié)果可以看出Thread-3線程鎖住了0x00000000f6360238,然后在等待0x00000000f6360228,而Thread-2卻卻相反,從下面每個(gè)線程的第一行ThreadController.java:42可以看到死鎖的代碼在哪個(gè)地方,進(jìn)而排查出問(wèn)題所在。
"Thread-3":
at com.example.threaddemo.ThreadController.lambda$getThread$1(ThreadController.java:42)
- waiting to lock <0x00000000f6360228> (a java.lang.Object)
- locked <0x00000000f6360238> (a java.lang.Object)
at com.example.threaddemo.ThreadController$$Lambda$464/550716470.run(Unknown Source)
at java.lang.Thread.run(Thread.java:750)
"Thread-2":
at com.example.threaddemo.ThreadController.lambda$getThread$0(ThreadController.java:30)
- waiting to lock <0x00000000f6360238> (a java.lang.Object)
- locked <0x00000000f6360228> (a java.lang.Object)
at com.example.threaddemo.ThreadController$$Lambda$463/1326723928.run(Unknown Source)
at java.lang.Thread.run(Thread.java:750)
但用jstack分析死鎖的話,在調(diào)用鏈很長(zhǎng)的情況下,也很難定位,這時(shí)可以用使用Arthas進(jìn)行分析
thread -b
?可以準(zhǔn)確知道: 死鎖在代碼的中的第幾行
實(shí)戰(zhàn)案例2:jstack分析CPU過(guò)高問(wèn)題
?案例代碼
public class CpuMath{
public static final int initData = 666;
public static User user = new User();
public int compute() {
int a = 1;
int b = 2;
int c = (a + b) * 100;
return c;
}
public static void main(String[] args) {
CpuMath cpuMath= new CpuMath();
while (true){
cpuMath.compute();
}
}
}
排查命令流程
1. top
????????獲取各個(gè)進(jìn)程的CPU和內(nèi)存情況,并且找到CPU飆高的進(jìn)程ID,比如進(jìn)程ID=10843
2. top -p 進(jìn)程ID
??????? 顯示你的java進(jìn)程的CPU和內(nèi)存占用情況
3. H
??????? 按H,可以獲取每個(gè)線程的CPU和內(nèi)存占用情況,如果線程ID=46915
4.? jstack 進(jìn)程ID | grep -A 10? 十六進(jìn)制的線程ID
??????? 通過(guò)上面的命令,可以得到線程的堆棧信息后10行信息,從堆棧中可以發(fā)現(xiàn)導(dǎo)致CPU飆高的調(diào)用方法。從打印的堆棧信息可以看出,導(dǎo)致CPU飚高的代碼在ThreadController類(lèi)getThread方法的第21行
柚子快報(bào)激活碼778899分享:JVM之jstack命令解析
精彩文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。