我正在编写JVMTI代码来剖析Java程序,这通常需要使用函数AsyncGetCallTrace在固定的时间间隔从随机线程获取堆栈跟踪。因此,我能够获得CallTrace结构,每个结构都包含一个CallFrame结构数组,这些数组包含有关堆栈跟踪中各个帧的数据。具体来说,这些数据包括:jmethodID method_id(框架所在的Java方法的ID)和:jint lineno(据我所知,该文件在.class文件中该方法的BCI)。我似乎找不到使用JVMTI框架将此“lineno”转换为相应的源代码行号的方法(至少参见/usr/lib/jvm/java-6-sun/include中的文件jvmti.h)。在Linux上)。实际上,即使在JVMTI框架之外,到目前为止,我在网络上唯一能找到的就是http://jakarta.apache.org/bcel/apidocs/org/apache/bcel/classfile/LineNumberTable.html,但这甚至可能无法实现我想要的功能,并且需要额外的安装,并且需要我处理数据,它是由C++ JMVTI代码使用单独的Java程序生成的。
如果有人知道如何从JVMTI内部(甚至以任何方式)将BCI转换为源代码行号,请提供帮助!
[如果有人对这一领域非常了解,请告诉我,因为我还有其他问题要问。
最佳答案
我想我有点想通了。使用的主要方法是jvmti-> GetLineNumberTable(...),它将填充jvmtiLineNumberEntry数组。给定BCI行号n(将其映射到源行号),可以测试哪个int i为:jvmtiLineNumberEntryArray [i]
一个问题是AsyncGetCallTrace出于某种原因始终返回奇怪的BCI,因此尽管映射为提供了精确的源代码行号,但它们仍不是准确的,因为原始BCI不准确。为什么会这样,我不知道。我希望使用Sun Studio探查器(也使用AsyncGetCallTrace)来测试返回的行号是否与探查器的行号相同。在这种情况下,AsyncGetCallTrace函数不正确。但是到目前为止,使用Sun Studio本身就是一个挑战。 如果有人知道如何使用此工具,请提供帮助!
一个更大的问题是Java方法通常是内联的,因此行号并不总是正确地映射。实际上,这可能是导致上面段落中所述问题的原因,尽管根据我所看到的数字来看,这似乎不太可能。以下是有关解决内联问题的一些信息:http://developer.amd.com/documentation/articles/pages/JVMTIEventPiggybacking.aspx