java如何在应用代码里捕获线程堆栈

 更新时间:2023年12月20日 11:01:44   作者:codecraft  
这篇文章主要为大家介绍了java如何在应用代码里捕获线程堆栈实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

本文主要研究一下如何在应用代码里捕获线程堆栈

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来获取线程堆栈

小结

在java运行时可以通过Thread.getAllStackTraces()、ManagementFactory.getThreadMXBean().dumpAllThreads来获取当前进程的线程堆栈信息,也可以通过Process调用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信息,而前面两个方法dump出来的没有nid这个信息。

以上就是java如何在应用代码里捕获线程堆栈的详细内容,更多关于java线程堆栈捕获的资料请关注脚本之家其它相关文章!

相关文章

  • java内存优化的方法总结

    java内存优化的方法总结

    在本篇文章里小编给大家分享的是一篇关于java内存优化的方法总结内容,有需要的朋友们可以学习下。
    2021-06-06
  • SpringBoot整合logback的示例代码

    SpringBoot整合logback的示例代码

    Logback是由log4j创始人设计的又一个开源日志组件,logback分为三个模块,在文章开头给大家介绍的很明确,接下来通过本文重点介绍下SpringBoot整合logback的方法,需要的朋友可以参考下
    2022-04-04
  • 详解Java编程中throw和throws子句的使用方法

    详解Java编程中throw和throws子句的使用方法

    这篇文章主要介绍了详解Java编程中throw和throws子句的使用方法,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • Springboot整合ip2region实现用户ip归属地获取

    Springboot整合ip2region实现用户ip归属地获取

    ip2region是一个离线IP地址定位库和IP定位数据管理框架,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现,下面我们来看看如何使用ip2region实现用户ip归属地获取吧
    2025-05-05
  • springboot在idea下debug调试热部署问题

    springboot在idea下debug调试热部署问题

    这篇文章主要介绍了springboot在idea下debug调试热部署问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Mybatis如何自动生成数据库表的实体类

    Mybatis如何自动生成数据库表的实体类

    这篇文章主要介绍了Mybatis自动生成数据库表的实体类的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java多线程ThreadPoolExecutor详解

    Java多线程ThreadPoolExecutor详解

    这篇文章主要介绍了Java多线程ThreadPoolExecutor详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • Java编程中实现Condition控制线程通信

    Java编程中实现Condition控制线程通信

    这篇文章主要介绍了Java编程中实现Condition控制线程通信,简单介绍了Java中控制线程通信的方法,以及对condition的解析和实例,具有一定参考价值,需要的朋友可以了解下。
    2017-11-11
  • java实现银行管理系统

    java实现银行管理系统

    这篇文章主要为大家详细介绍了java实现银行管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • Spring实现上拉刷新和下拉加载效果

    Spring实现上拉刷新和下拉加载效果

    这篇文章主要为大家详细介绍了Spring实现上拉刷新和下拉加载效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12

最新评论