java - 鉴于 JFR 承诺低开销,它如何设法记录堆栈跟踪?
问题描述
通过https://www.oracle.com/technetwork/java/javaseproducts/mission-control/java-mission-control-wp-2008279.pdf,我遇到了以下引用:
当今用于监视、管理和分析 Java 运行时的大多数技术都使用相当侵入性的技术,例如字节码检测和 JVMTI。
这让我想知道 JFR 进行堆栈跟踪采样的方式。
我在网上能找到的最接近答案的是这篇博文:http: //psy-lob-saw.blogspot.com/2016/06/the-pros-and-cons-of-agct.html,提到诸如 Honest profiler 和 async-profiler 之类的分析器使用了未记录的 AsyncGetCallTrace,但事实是它没有提及 JFR 进行堆栈跟踪采样/记录的具体方式。
这里有没有人对这个主题的 JFR 内部有任何见解?
解决方案
JFR 维护一个定期唤醒的线程,即每 10 毫秒一次,并通过发送信号挂起少量正在运行的 Java 线程。然后它遍历挂起线程的堆栈以查看正在执行的方法。它计算堆栈帧的哈希值,然后检查之前是否已找到该堆栈跟踪。
如果不是这种情况,它会将堆栈帧添加到哈希表并碰撞一个计数器,该计数器成为堆栈跟踪的 id。然后它将 id 作为执行示例事件发出,该事件最终在另一个线程定期刷新到磁盘的缓冲区(无锁)中。如果一个 id 是新的,它还会记下与该 id 对应的完整堆栈跟踪,以便稍后可以由解析器解析堆栈跟踪。
如果你想更深入地挖掘,你可以看看源代码。
http://hg.openjdk.java.net/jdk/jdk/file/tip/src/hotspot/share/jfr/periodic/sampling
线程如何挂起取决于平台。在以下文件中,您可以找到 Linux 实现。
http://hg.openjdk.java.net/jdk/jdk/file/tip/src/hotspot/os/linux/os_linux.cpp
推荐阅读
- c - 并行内循环减慢程序
- java - java serviceability agent vs jmc vs visualvm
- xml - rabbitmq xml配置应用项目的文件夹结构
- android - OpenCV - NDK 更新后对 'cv::CascadeClassifier::detectMultiScale()' 的未定义引用
- ios - 在框架错误中包含非模块化标头
- reactjs - React.js 路由器不同的背景图片
- django - Django 单元测试(使用 DRF):如何测试 Passwordresetview?
- javascript - 为什么我不能使用 Apollo Link State 添加待办事项?
- python-3.x - 如何在通过python3读取一行csv文件时删除前一行
- import - mscrm 导入更新列映射引用属性