java如何在應(yīng)用代碼里捕獲線程堆棧
序
本文主要研究一下如何在應(yīng)用代碼里捕獲線程堆棧
getRunnableStackTraces
org/h2/util/Profiler.java
private static List<Object[]> getRunnableStackTraces() {
ArrayList<Object[]> list = new ArrayList<>();
Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces();
for (Map.Entry<Thread, StackTraceElement[]> entry : map.entrySet()) {
Thread t = entry.getKey();
if (t.getState() != Thread.State.RUNNABLE) {
continue;
}
StackTraceElement[] dump = entry.getValue();
if (dump == null || dump.length == 0) {
continue;
}
list.add(dump);
}
return list;
}h2的Profiler的getRunnableStackTraces方法通過Thread.getAllStackTraces()來收集線程堆棧
readRunnableStackTraces
org/h2/util/Profiler.java
private static List<Object[]> readRunnableStackTraces(int pid) {
try {
String jstack = exec("jstack", Integer.toString(pid));
LineNumberReader r = new LineNumberReader(
new StringReader(jstack));
return readStackTrace(r);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static String exec(String... args) {
ByteArrayOutputStream err = new ByteArrayOutputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
Process p = Runtime.getRuntime().exec(args);
copyInThread(p.getInputStream(), out);
copyInThread(p.getErrorStream(), err);
p.waitFor();
String e = new String(err.toByteArray(), StandardCharsets.UTF_8);
if (e.length() > 0) {
throw new RuntimeException(e);
}
return new String(out.toByteArray(), StandardCharsets.UTF_8);
} catch (Exception e) {
throw new RuntimeException(e);
}
}h2的Profiler的readRunnableStackTraces方法則是基于給定的pid使用jstack來捕獲線程堆棧
CommandProcessor
sun/jvm/hotspot/CommandProcessor.java
new Command("jstack", "jstack [-v]", false) {
public void doit(Tokens t) {
boolean verbose = false;
if (t.countTokens() > 0 && t.nextToken().equals("-v")) {
verbose = true;
}
StackTrace jstack = new StackTrace(verbose, true);
jstack.run(out);
}
}sun.jvm.hotspot包的CommandProcessor提供了對jstack的支持
ThreadDumpEndpoint
org/springframework/boot/actuate/management/ThreadDumpEndpoint.java
@ReadOperation(produces = "text/plain;charset=UTF-8")
public String textThreadDump() {
return getFormattedThreadDump(this.plainTextFormatter::format);
}
private <T> T getFormattedThreadDump(Function<ThreadInfo[], T> formatter) {
return formatter.apply(ManagementFactory.getThreadMXBean().dumpAllThreads(true, true));
}springboot的ThreadDumpEndpoint則使用的是ManagementFactory.getThreadMXBean().dumpAllThreads來獲取線程堆棧
小結(jié)
在java運(yùn)行時(shí)可以通過Thread.getAllStackTraces()、ManagementFactory.getThreadMXBean().dumpAllThreads來獲取當(dāng)前進(jìn)程的線程堆棧信息,也可以通過Process調(diào)用jstack命令,值得注意的是jstack捕獲的線程堆棧包含了nid
(比如"C2 CompilerThread0" #7 daemon prio=9 os_prio=31 cpu=481.27ms elapsed=36.74s tid=0x00007fb08c068400 nid=0x6803 waiting on condition [0x0000000000000000])
也就是top -H -p pid中展示的PID信息,而前面兩個(gè)方法dump出來的沒有nid這個(gè)信息。
以上就是java如何在應(yīng)用代碼里捕獲線程堆棧的詳細(xì)內(nèi)容,更多關(guān)于java線程堆棧捕獲的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Springboot整合ip2region實(shí)現(xiàn)用戶ip歸屬地獲取
ip2region是一個(gè)離線IP地址定位庫和IP定位數(shù)據(jù)管理框架,提供了眾多主流編程語言的 xdb 數(shù)據(jù)生成和查詢客戶端實(shí)現(xiàn),下面我們來看看如何使用ip2region實(shí)現(xiàn)用戶ip歸屬地獲取吧2025-05-05
springboot在idea下debug調(diào)試熱部署問題
這篇文章主要介紹了springboot在idea下debug調(diào)試熱部署問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02
Mybatis如何自動生成數(shù)據(jù)庫表的實(shí)體類
這篇文章主要介紹了Mybatis自動生成數(shù)據(jù)庫表的實(shí)體類的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
Java編程中實(shí)現(xiàn)Condition控制線程通信
這篇文章主要介紹了Java編程中實(shí)現(xiàn)Condition控制線程通信,簡單介紹了Java中控制線程通信的方法,以及對condition的解析和實(shí)例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11
Spring實(shí)現(xiàn)上拉刷新和下拉加載效果
這篇文章主要為大家詳細(xì)介紹了Spring實(shí)現(xiàn)上拉刷新和下拉加載效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12

