我正在编写一个简短的分析器(用 C 语言),其目的是定期打印各种 Java 客户端中线程的堆栈跟踪。我必须使用未记录的函数 AsyncGetCallTrace 而不是 GetStackTrace 来最大限度地减少入侵并允许堆栈跟踪,而不管线程状态如何。该函数的源代码可以在这里找到: http://download.java.net/openjdk/jdk6/promoted/b20/openjdk-6-src-b20-21_jun_2010.tar.gz在 hotspot/src/share/vm/prims/forte.cpp 中。我找到了一些记录 JVMTI、信号处理和计时的手册页,以及一个详细介绍如何设置 AsyncGetCallTrace 调用的博客:http://jeremymanson.blogspot.com/2007/05/profiling-with-jvmtijvmpi-sigprof-and.html。

本博客缺少的是实际调用信号处理程序中的函数的代码(作者假设读者可以自己完成此操作)。我正在寻求帮助来做到这一点。我不确定如何以及在哪里创建 struct ASGCT_CallTrace (以及内部 struct ASGCT_CallFrame),如上述文件 forte.cpp 中所定义。struct ASGCT_CallTrace 是传递给 AsyncGetCallTrace 的参数之一,因此我确实需要创建它,但我不知道如何获取其字段的正确值:JNIEnv *env_id、jint num_frames 和 JVMPI_CallFrame 帧。此外,我不知道传递给 AsyncGetCallTrace 的第三个参数是什么(void ucontext)应该是?

上述问题是我遇到的主要问题。然而,我面临的其他问题包括:[1] SIGPROF 似乎不是由计时器精确地按指定的时间间隔引发的,而是频率稍低一些。也就是说,如果我设置了计时器每秒发送一个sigprof(1秒,0 USEC),则在5秒的运行中,我的速度少于5 Sigprof处理程序输出(通常为1-3)[2] Sigprof Handler输出在Java代码中的螺纹中完全不会出现。因此,如果每秒发送一个 SIGPROF,并且我有 Thread.sleep(5000);,那么在执行该代码期间我将不会获得任何处理程序输出。

任何帮助,将不胜感激。其他详细信息(以及部分代码和示例输出)将根据要求发布。

谢谢!

有帮助吗?

解决方案

我终于得到了一个积极的结果,但由于这里几乎没有引起讨论,所以我自己的答案将很简短。

ASGCT_CallTrace 结构(以及底层 ASGCT_CallFrame 数组)可以简单地在信号处理程序中声明,因此仅存在堆栈:ASGCT_CallTrace 跟踪;JNIEnv *env;global_VM_pointer->AttachCurrentThread((void **) &env, NULL);跟踪.env_id = env;跟踪.num_frames = 0;ASGCT_CallFrame存储[25];跟踪.frames = 存储;

以下获取uContext:ucontext_t uContext;获取上下文(&uContext);

然后调用就是:AsyncGetCallTrace(&trace, 25, &uContext);

我确信在此过程中我还必须注意其他一些细微差别,但我并没有真正记录它们。我不确定我是否可以透露我拥有的完整当前代码,该代码成功地以固定时间间隔异步请求并获取任何 java 程序的堆栈跟踪。但如果有人对同一问题感兴趣或陷入困境,我现在可以提供帮助(我认为)。

关于另外两个问题:[1] 如果线程正在睡眠并生成 SIGPROF,则该线程仅在唤醒后处理该信号。这是正常的,因为处理信号是线程的工作。[2] 计时器缺陷似乎不再出现。也许是我量错了。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top