这是 this one 的后续问题
因此,我不断从“程序化访问”的角度探索现代分析器的功能,并且遇到了一些超出我理解的东西。
这次我偶然发现了 JProfiler 中的“分配调用树”功能:
我确实看到,为了获得这种信息,我必须默认以 1/10 的速率触发采样分配,然后指定(最好)将记录分配的分类的包。
第一步
第二步
但是我真的不明白有关调用堆栈的信息如何与有关分配对象的信息“匹配”。
当然,我的问题不是关于 JProfiler 的实现细节,我理解它是一个商业工具,代码和一切都很接近,而是关于如何检索这种信息的一般理解。
我最初的猜测是,它以某种方式“检测”已经加载的类文件以“拦截”这些对象的每个分配(采样率不会太慢)但是然后呢?它是否调用类似 Thread.currentThread().getStackTrace()
并记录导致分配的实际堆栈跟踪?
另一方面,它在“采样模式”(与仪器相反)中激活+存在性能问题 - 这对我来说听起来非常昂贵(阅读,不应该在生产中使用),但我可能是错误的,所以任何建议将不胜感激。
最佳答案
My initial guess is that it somehow "instruments" the already-loaded class files to "intercept" each and every allocation for these objects
自 Java 11 交付以来 JEP 331它在 native JVMTI 中使用这些功能来采样分配。在 Java 11 之前,它检测
java.lang.Object
构造函数。至于调用堆栈,这取决于使用的是检测还是采样。对于检测,它使用检测已经构建的调用堆栈。对于采样,采样构建的调用栈不够精确,所以queries the call stack through JVMTI .Does it call something like Thread.currentThread().getStackTrace()
对于采样,它有点像那样,但是在 Java 中这样做会产生巨大的开销,因为有许多二级分配。 JVMTI 是 native 接口(interface),可以更有效地执行此操作。
关于java - JVM 以编程方式获取分配调用堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67156225/