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方法通過(guò)Thread.getAllStackTraces()來(lái)收集線程堆棧
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來(lái)捕獲線程堆棧
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提供了對(duì)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來(lái)獲取線程堆棧
小結(jié)
在java運(yùn)行時(shí)可以通過(guò)Thread.getAllStackTraces()、ManagementFactory.getThreadMXBean().dumpAllThreads來(lái)獲取當(dāng)前進(jìn)程的線程堆棧信息,也可以通過(guò)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出來(lái)的沒(méi)有nid這個(gè)信息。
以上就是java如何在應(yīng)用代碼里捕獲線程堆棧的詳細(xì)內(nèi)容,更多關(guān)于java線程堆棧捕獲的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
通過(guò)實(shí)例解析Java類初始化和實(shí)例初始化
這篇文章主要介紹了通過(guò)實(shí)例解析Java類初始化和實(shí)例初始化,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11SpringSecurity實(shí)現(xiàn)踢出指定用戶的示例
SpringSecurity中使用SessionRegistryImpl類可以獲取session信息并踢出用戶,這篇文章主要介紹了SpringSecurity實(shí)現(xiàn)踢出指定用戶的示例,需要的朋友可以參考下2025-03-03手把手教你SpringBoot過(guò)濾器N種注冊(cè)方式
這篇文章主要介紹了手把手教你SpringBoot過(guò)濾器N種注冊(cè)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06spring boot 本地圖片不能加載(圖片路徑)的問(wèn)題及解決方法
這篇文章主要介紹了spring boot 本地圖片不能加載(圖片路徑)的問(wèn)題,解決的辦法其實(shí)很簡(jiǎn)單,只要寫(xiě)一個(gè)配置文件,也就是圖片位置的轉(zhuǎn)化器,原理是虛擬一個(gè)在服務(wù)器上的文件夾,與本地圖片的位置進(jìn)行匹配。需要的朋友可以參考下2018-04-04Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單計(jì)算器
這篇文章主要介紹了Java實(shí)現(xiàn)一個(gè)簡(jiǎn)單計(jì)算器,文章我圍繞實(shí)現(xiàn)簡(jiǎn)單計(jì)算器的相關(guān)代碼展現(xiàn)全文,具有一定的參考價(jià)值,需要的小伙伴可以參考一下,2022-01-01使用@RequestBody配合@Valid校驗(yàn)入?yún)?shù)
這篇文章主要介紹了使用@RequestBody配合@Valid校驗(yàn)入?yún)?shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03說(shuō)說(shuō)字符串轉(zhuǎn) OffSetDateTime 你真的會(huì)用嗎
這篇文章主要介紹了字符串轉(zhuǎn) OffSetDateTime 你真的會(huì)用嗎?具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08Springboot整合hibernate validator 全局異常處理步驟詳解
本文分步驟給大家介紹Springboot整合hibernate validator 全局異常處理,補(bǔ)呢文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2024-01-01