首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JVM如何收集ThreadDump不足功能

问JVM如何收集ThreadDump不足功能
EN

Stack Overflow用户
提问于 2021-04-13 19:05:46
回答 1查看 196关注 0票数 3

请解释JVM是如何收集ThreadDump不足的。

我不明白它是如何收集非CPU线程的堆栈跟踪(等待磁盘IO、网络、非自愿上下文切换)。

例如,linux perf只收集有关CPU线程(使用CPU周期)的信息。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-13 22:23:56

我将以HotSpot JVM为例。

JVM维护所有Java线程的列表:对于每个线程,它都有一个相应的VM结构。根据执行上下文的不同,线程可以处于下列状态之一(HotSpot知道每个线程的当前状态,因为它负责切换状态):

  • in_Java -线程正在执行Java代码,无论是在解释器中还是在JIT编译的方法中;
  • in_vm -一个线程在VM运行时函数中;
  • in_native -一个线程在JNI上下文中运行一个本机方法;
  • 也有过渡状态,但为了简单起见,让我们跳过它们。

非cpu线程只能有

  • in_native状态:所有套接字I/O、磁盘I/O和其他阻塞操作仅在本机代码中执行;
  • in_vm状态,当线程在VM互斥对象上被阻塞时。

每当JVM调用本机方法或获取竞争互斥对象时,它都会将最后一个Java指针存储到Thread结构中。

现在关键的部分是:HotSpot JVM只在 安全点上获得线程转储。

当您请求线程转储时,JVM请求停止世界暂停。处于in_Java状态的所有线程都会在最近的safepoint停止,在那里JVM知道如何遍历堆栈。

处于in_native状态的线程不会停止,但它们不需要停止。HotSpot知道它们的最后一个Java框架,因为指针存储在Thread结构中。JVM知道顶级Java框架,就可以找到它的调用者,然后找到调用者的调用者,依此类推。

​

​

这里重要的是,不管本机方法做什么,堆栈的Java部分都是“冻结”的。堆栈的顶部(本机)可以来回更改,而底层部分(Java)保持不变。它不能改变,因为JVM在从in_native到in_Java的每个开关上都检查挂起的safepoint操作:如果一个本机方法返回,并且VM当前正在运行停止世界操作,当前线程将一直阻塞直到操作结束。

因此,获取线程转储包括

  1. 在安全点停止所有in_Java和in_vm线程;
  2. 遍历JVM维护的全局线程列表;
  3. 如果一个线程正在运行本机方法,它的顶层Java框架存储在一个线程结构中;如果一个线程正在运行Java代码,它的顶部框架对应于当前正在执行的Java方法。
  4. 每个帧都有一个指向前一个帧的链接,因此给定顶部帧,JVM可以构造到底部的整个堆栈跟踪。
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67080990

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档