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线程堆栈捕获的资料请关注脚本之家其它相关文章!

相关文章

  • mybatis参数类型不匹配错误argument type mismatch的处理方案

    mybatis参数类型不匹配错误argument type mismatch的处理方案

    这篇文章主要介绍了mybatis参数类型不匹配错误argument type mismatch的处理方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java枚举类用法实例

    Java枚举类用法实例

    这篇文章主要介绍了Java枚举类用法,实例分析了java中枚举类的实现与使用技巧,需要的朋友可以参考下
    2015-05-05
  • SpringBoot浅析安全管理之Shiro框架

    SpringBoot浅析安全管理之Shiro框架

    安全管理是软件系统必不可少的的功能。根据经典的“墨菲定律”——凡是可能,总会发生。如果系统存在安全隐患,最终必然会出现问题,这篇文章主要介绍了SpringBoot安全管理Shiro框架的使用
    2022-08-08
  • Java.SE数组的一些常见练习题

    Java.SE数组的一些常见练习题

    数组可以看成是相同类型元素的一个集合,在内存中是一段连续的空间,这篇文章主要给大家介绍了关于Java.SE数组的一些常见练习题,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • SpringBoot动态数据源连接测试的操作详解

    SpringBoot动态数据源连接测试的操作详解

    这篇文章主要介绍了SpringBoot动态数据源连接测试的操作步骤,文中通过代码示例和图文结合的方式给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-03-03
  • SpringBoot整合OpenApi的实践

    SpringBoot整合OpenApi的实践

    本文主要介绍了SpringBoot整合OpenApi,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Spring WebFlux实现参数校验的示例代码

    Spring WebFlux实现参数校验的示例代码

    请求参数校验,在实际的应用中很常见,网上的文章大部分提供的使用注解的方式做参数校验。本文主要介绍 Spring Webflux Function Endpoint 使用 Spring Validation 来校验请求的参数。感兴趣的可以了解一下
    2021-08-08
  • 详解Spring Boot 使用Spring security 集成CAS

    详解Spring Boot 使用Spring security 集成CAS

    本篇文章主要介绍了详解Spring Boot 使用Spring security 集成CAS,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • SpringBoot使用Maven打包异常-引入外部jar的问题及解决方案

    SpringBoot使用Maven打包异常-引入外部jar的问题及解决方案

    这篇文章主要介绍了SpringBoot使用Maven打包异常-引入外部jar,需要的朋友可以参考下
    2020-06-06
  • java return用法实例详解

    java return用法实例详解

    在本篇文章里小编给大家整理的是关于java return用法以及相关知识点总结,需要的朋友们参考下。
    2019-08-08

最新评论