最牛逼的故障診斷工具!秒級定位線上問題
往期熱門文章:
1、新技能 MyBatis 千萬數(shù)據(jù)表,快速分頁! 2、常見的SQL面試題:經(jīng)典50例 3、事務注解 @Transactional 失效的3種場景及解決辦法 4、看看人家SpringBoot的全局異常處理多么優(yōu)雅... 5、代碼總是被嫌棄寫的太爛?裝上這個IDEA插件再試試!
背景

1. top oder by with P:1040 // 首先按進程負載排序找到 axLoad(pid)
2. top -Hp 進程PID:1073 // 找到相關負載 線程PID
3. printf “0x%x\n”線程PID: 0x431 // 將線程PID轉(zhuǎn)換為 16進制,為后面查找 jstack 日志做準備
4. jstack 進程PID | vim +/十六進制線程PID - // 例如:jstack 1040|vim +/0x431 -
快速安裝使用:
source <(curl -fsSL https://raw.githubusercontent.com/oldratlee/useful-scripts/master/test-cases/self-installer.sh)
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexLoad {
public static void main(String[] args) {
String[] patternMatch = {"([\\w\\s]+)+([+\\-/*])+([\\w\\s]+)",
"([\\w\\s]+)+([+\\-/*])+([\\w\\s]+)+([+\\-/*])+([\\w\\s]+)"};
List patternList = new ArrayList();
patternList.add("Avg Volume Units product A + Volume Units product A");
patternList.add("Avg Volume Units / Volume Units product A");
patternList.add("Avg retailer On Hand / Volume Units Plan / Store Count");
patternList.add("Avg Hand Volume Units Plan Store Count");
patternList.add("1 - Avg merchant Volume Units");
patternList.add("Total retailer shipment Count");
for (String s :patternList ){
for(int i=0;i<patternmatch.length;i++){
Pattern pattern = Pattern.compile(patternMatch[i]);
Matcher matcher = pattern.matcher(s);
System.out.println(s);
if (matcher.matches()) {
System.out.println("Passed");
}else
System.out.println("Failed;");
}
}
}
}

怎么使用呢?
show-busy-java-threads.sh
# 從 所有的 Java進程中找出最消耗CPU的線程(缺省5個),打印出其線程棧。
show-busy-java-threads.sh -c <要顯示的線程棧數(shù)>
show-busy-java-threads.sh -c <要顯示的線程棧數(shù)> -p <指定的Java Process>
# -F選項:執(zhí)行jstack命令時加上-F選項(強制jstack),一般情況不需要使用
show-busy-java-threads.sh -p <指定的Java Process> -F
show-busy-java-threads.sh -s <指定jstack命令的全路徑>
# 對于sudo方式的運行,JAVA_HOME環(huán)境變量不能傳遞給root,
# 而root用戶往往沒有配置JAVA_HOME且不方便配置,
# 顯式指定jstack命令的路徑就反而顯得更方便了
show-busy-java-threads.sh -a <輸出記錄到的文件>
show-busy-java-threads.sh -t <重復執(zhí)行的次數(shù)> -i <重復執(zhí)行的間隔秒數(shù)>
# 缺省執(zhí)行一次;執(zhí)行間隔缺省是3秒
##############################
# 注意:
##############################
# 如果Java進程的用戶 與 執(zhí)行腳本的當前用戶 不同,則jstack不了這個Java進程。
# 為了能切換到Java進程的用戶,需要加sudo來執(zhí)行,即可以解決:
sudo show-busy-java-threads.sh
work@dev_zz_Master 10.48.186.32 23:45:50 ~/demo >
bash show-busy-java-threads.sh
[1] Busy(96.2%) thread(8577/0x2181) stack of java process(8576) under user(work):
"main" prio=10 tid=0x00007f0c64006800 nid=0x2181 runnable [0x00007f0c6a64a000]
java.lang.Thread.State: RUNNABLE
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4168)
at java.util.regex.Pattern$Loop.match(Pattern.java:4295)
...
at java.util.regex.Matcher.match(Matcher.java:1127)
at java.util.regex.Matcher.matches(Matcher.java:502)
at RegexLoad.main(RegexLoad.java:27)
[2] Busy(1.5%) thread(8591/0x218f) stack of java process(8576) under user(work):
"C2 CompilerThread1" daemon prio=10 tid=0x00007f0c64095800 nid=0x218f waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
[3] Busy(0.8%) thread(8590/0x218e) stack of java process(8576) under user(work):
"C2 CompilerThread0" daemon prio=10 tid=0x00007f0c64093000 nid=0x218e waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE
[4] Busy(0.2%) thread(8593/0x2191) stack of java process(8576) under user(work):
"VM Periodic Task Thread" prio=10 tid=0x00007f0c640a2800 nid=0x2191 waiting on condition
[5] Busy(0.1%) thread(25159/0x6247) stack of java process(25137) under user(work):
"VM Periodic Task Thread" prio=10 tid=0x00007f13340b4000 nid=0x6247 waiting on condition
work@dev_zz_Master 10.48.186.32 23:46:04 ~/demo >
import java.util.*;
public class SimpleDeadLock extends Thread {
public static Object l1 = new Object();
public static Object l2 = new Object();
private int index;
public static void main(String[] a) {
Thread t1 = new Thread1();
Thread t2 = new Thread2();
t1.start();
t2.start();
}
private static class Thread1 extends Thread {
public void run() {
synchronized (l1) {
System.out.println("Thread 1: Holding lock 1...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 1: Waiting for lock 2...");
synchronized (l2) {
System.out.println("Thread 2: Holding lock 1 & 2...");
}
}
}
}
private static class Thread2 extends Thread {
public void run() {
synchronized (l2) {
System.out.println("Thread 2: Holding lock 2...");
try { Thread.sleep(10); }
catch (InterruptedException e) {}
System.out.println("Thread 2: Waiting for lock 1...");
synchronized (l1) {
System.out.println("Thread 2: Holding lock 2 & 1...");
}
}
}
}
}

如何用工具定位

免費實用的腳本工具大禮包
(1)show-duplicate-java-classes
# 查找當前目錄下所有Jar中的重復類
show-duplicate-java-classes
# 查找多個指定目錄下所有Jar中的重復類
show-duplicate-java-classes path/to/lib_dir1 /path/to/lib_dir2
# 查找多個指定Class目錄下的重復類。Class目錄 通過 -c 選項指定
show-duplicate-java-classes -c path/to/class_dir1 -c /path/to/class_dir2
# 查找指定Class目錄和指定目錄下所有Jar中的重復類的Jar
show-duplicate-java-classes path/to/lib_dir1 /path/to/lib_dir2 -c path/to/class_dir1 -c path/to/class_dir2
例如:
# 在war模塊目錄下執(zhí)行,生成war文件
$ mvn install
...
# 解壓war文件,war文件中包含了應用的依賴的Jar文件
$ unzip target/*.war -d target/war
...
# 檢查重復類
$ show-duplicate-java-classes -c target/war/WEB-INF/classes target/war/WEB-INF/lib
...
(2)find-in-jars
find-in-jars 'log4j\.properties'
find-in-jars 'log4j\.xml$' -d /path/to/find/directory
find-in-jars log4j\\.xml
find-in-jars 'log4j\.properties|log4j\.xml'
$ ./find-in-jars 'Service.class$'
./WEB-INF/libs/spring-2.5.6.SEC03.jar!org/springframework/stereotype/Service.class
./rpc-benchmark-0.0.1-SNAPSHOT.jar!com/taobao/rpc/benchmark/service/HelloService.class
(3)housemd pid [java_home]
查看加載類 跟蹤方法 查看環(huán)境變量 查看對象屬性值 詳細信息請參考: https://github.com/CSUG/HouseMD/wiki/UserGuideCN
(4)jvm pid
========線程相關=======
1 : 查看占用cpu最高的線程情況
2 : 打印所有線程
3 : 打印線程數(shù)
4 : 按線程狀態(tài)統(tǒng)計線程數(shù)
========GC相關=======
5 : 垃圾收集統(tǒng)計(包含原因)可以指定間隔時間及執(zhí)行次數(shù),默認1秒, 10次
6 : 顯示堆中各代的空間可以指定間隔時間及執(zhí)行次數(shù),默認1秒,5次
7 : 垃圾收集統(tǒng)計??梢灾付ㄩg隔時間及執(zhí)行次數(shù),默認1秒, 10次
8 : 打印perm區(qū)內(nèi)存情況*會使程序暫停響應*
9 : 查看directbuffer情況
========堆對象相關=======
10 : dump heap到文件*會使程序暫停響應*默認保存到`pwd`/dump.bin,可指定其它路徑
11 : 觸發(fā)full gc。*會使程序暫停響應*
12 : 打印jvm heap統(tǒng)計*會使程序暫停響應*
13 : 打印jvm heap中top20的對象。*會使程序暫停響應*參數(shù):1:按實例數(shù)量排序,2:按內(nèi)存占用排序,默認為1
14 : 觸發(fā)full gc后打印jvm heap中top20的對象。*會使程序暫停響應*參數(shù):1:按實例數(shù)量排序,2:按內(nèi)存占用排序,默認為1
15 : 輸出所有類裝載器在perm里產(chǎn)生的對象??梢灾付ㄩg隔時間及執(zhí)行次數(shù)
========其它=======
16 : 打印finalzer隊列情況
17 : 顯示classloader統(tǒng)計
18 : 顯示jit編譯統(tǒng)計
19 : 死鎖檢測
20 : 等待X秒,默認為1
q : exit
進入jvm工具后可以輸入序號執(zhí)行對應命令
可以一次執(zhí)行多個命令,用分號";"分隔,如:1;3;4;5;6
每個命令可以帶參數(shù),用冒號":"分隔,同一命令的參數(shù)之間用逗號分隔,如:
Enter command queue:1;5:1000,100;10:/data1/output.bin
(5)greys[@IP:PORT]
查看加載類,方法信息 查看JVM當前基礎信息 方法執(zhí)行監(jiān)控(調(diào)用量,失敗率,響應時間等) 方法執(zhí)行數(shù)據(jù)觀測、記錄與回放(參數(shù),返回結果,異常信息等) 方法調(diào)用追蹤渲染 詳細信息請參考: https://github.com/oldmanpushcart/greys-anatomy/wiki
使用sjk對Java診斷、性能排查、優(yōu)化工具 ttop:監(jiān)控指定jvm進程的各個線程的cpu使用情況 jps: 強化版 hh: jmap -histo強化版 gc: 實時報告垃圾回收信息 更多信息請參考: https://github.com/aragozin/jvm-tools
來源:https://my.oschina.net/leejun2005/blog/1524687
最近熱文閱讀:
1、一次線上 JVM 調(diào)優(yōu)實踐,F(xiàn)ullGC 40 次/天到 10 天一次的優(yōu)化過程 2、新技能 MyBatis 千萬數(shù)據(jù)表,快速分頁! 3、常見的SQL面試題:經(jīng)典50例 4、事務注解 @Transactional 失效的3種場景及解決辦法 5、看看人家SpringBoot的全局異常處理多么優(yōu)雅... 6、代碼總是被嫌棄寫的太爛?裝上這個IDEA插件再試試! 7、60個相見恨晚的神器工具! 8、終于來了,IDEA 2021.1版本正式發(fā)布,完美支持WSL 2 9、面試被問事務注解 @Transactional 失效怎么解決? 10、CTO 說了,用錯 @Autowired 和 @Resource 的人可以領盒飯了 關注公眾號,你想要的Java都在這里
評論
圖片
表情
