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类初始化和实例初始化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • SpringSecurity实现踢出指定用户的示例

    SpringSecurity实现踢出指定用户的示例

    SpringSecurity中使用SessionRegistryImpl类可以获取session信息并踢出用户,这篇文章主要介绍了SpringSecurity实现踢出指定用户的示例,需要的朋友可以参考下
    2025-03-03
  • 手把手教你SpringBoot过滤器N种注册方式

    手把手教你SpringBoot过滤器N种注册方式

    这篇文章主要介绍了手把手教你SpringBoot过滤器N种注册方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • spring boot 本地图片不能加载(图片路径)的问题及解决方法

    spring boot 本地图片不能加载(图片路径)的问题及解决方法

    这篇文章主要介绍了spring boot 本地图片不能加载(图片路径)的问题,解决的办法其实很简单,只要写一个配置文件,也就是图片位置的转化器,原理是虚拟一个在服务器上的文件夹,与本地图片的位置进行匹配。需要的朋友可以参考下
    2018-04-04
  • Java实现一个简单计算器

    Java实现一个简单计算器

    这篇文章主要介绍了Java实现一个简单计算器,文章我围绕实现简单计算器的相关代码展现全文,具有一定的参考价值,需要的小伙伴可以参考一下,
    2022-01-01
  • 使用@RequestBody配合@Valid校验入参参数

    使用@RequestBody配合@Valid校验入参参数

    这篇文章主要介绍了使用@RequestBody配合@Valid校验入参参数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • Java线程阻塞工具LockSupport用法详解

    Java线程阻塞工具LockSupport用法详解

    Java中的LockSupport是一个用于线程同步的工具类,它提供了一种基于线程的阻塞和唤醒机制,LockSupport可以让线程在特定条件下阻塞挂起,等待其他线程发送信号来唤醒它,本文将通过一个小案例给大家介绍一下LockSupport怎么用,让你永远记住它
    2023-08-08
  • 说说字符串转 OffSetDateTime 你真的会用吗

    说说字符串转 OffSetDateTime 你真的会用吗

    这篇文章主要介绍了字符串转 OffSetDateTime 你真的会用吗?具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • Springboot整合hibernate validator 全局异常处理步骤详解

    Springboot整合hibernate validator 全局异常处理步骤详解

    本文分步骤给大家介绍Springboot整合hibernate validator 全局异常处理,补呢文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-01-01
  • Java多线程实现复制文件

    Java多线程实现复制文件

    这篇文章主要为大家详细介绍了Java多线程实现复制文件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03

最新评论