JVM如何通过程序获取分配调用栈

3
这是一个关于此问题的后续问题。
所以我从“编程访问”角度不断探索现代分析器的能力,并发现了一些超出我的理解范围的东西。
这次我偶然发现了JProfiler中的“分配调用树”功能:

Allocation Call Tree

我发现要获取这种信息,首先需要使用默认1/10的采样率触发分配,并指定(最好是)记录已分配类的包。

步骤1

Step 1

步骤2

Step 2

但我并不真正理解如何将有关调用堆栈的信息与分配对象的信息“匹配”。
当然,我的问题不是关于JProfiler的实现细节,我知道它是一个商业工具,有着紧密的代码等等,而是关于如何检索这种信息的一般理解。
我的初步猜测是它以某种方式“检测”已加载的类文件,以“拦截”为这些对象分配的每个操作(采样率不会太慢),但是接下来呢?它是否调用像Thread.currentThread().getStackTrace()这样的东西,并记录导致分配的实际堆栈跟踪?
另一方面,它处于“采样模式”(与仪器相对)+存在性能问题-这听起来对我来说非常昂贵(即不应在生产中使用),但我可能错了,因此任何建议都将不胜感激。
1个回答

3
我的初步猜测是,它以某种方式“仪器化”已加载的类文件,以便“拦截”这些对象的每个分配。自Java 11交付JEP 331以来,它使用本地JVMTI中的这些功能来采样分配。在Java 11之前,它会调用java.lang.Object构造函数进行仪器化。至于调用堆栈,则取决于是否使用仪器化或采样。对于仪器化,它使用仪器化已构建的调用堆栈。对于采样,通过采样构建的调用堆栈不够精确,因此它会通过JVMTI查询调用堆栈
它是否调用Thread.currentThread().getStackTrace()之类的东西?
对于采样而言,有点像那样,但在Java中这样做会因为许多次要分配而产生巨大的开销。JVMTI是一种本地接口,可以更有效地执行此操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接