4

我正在编写一个简短的分析器(用 C 语言),它旨在定期打印出各种 Java 客户端中线程的堆栈跟踪。我必须使用未记录的函数AsyncGetCallTrace而不是GetStackTrace最小化入侵并允许堆栈跟踪而不管线程状态如何。该函数的源代码可以在这里找到:http: //download.java.net/openjdk/jdk6/promoted/b20/openjdk-6-src-b20-21_jun_2010.tar.gz in 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.cppstruct ASGCT_CallTrace是传递给 的参数之一,AsyncGetCallTrace因此我确实需要创建它,但我不知道如何为其字段获取正确的值:JNIEnv *env_idjint num_framesJVMPI_CallFrame *frames。此外,我不知道传递给的第三个参数AsyncGetCallTrace (void* ucontext)应该是什么?

上述问题是我遇到的主要问题。但是,我面临的其他问题包括:

  1. SIGPROF计时器似乎并没有以指定的时间间隔准确地引发,而是不那么频繁。也就是说,如果我将计时器设置为每秒发送SIGPROF一次(1 秒,0 微秒),那么在 5 秒的运行中,我得到的处理程序输出少于 5 个SIGPROF(通常为 1-3 个)

  2. SIGPROFThread.sleep在 Java 代码中,处理程序输出根本不会出现。因此,如果SIGPROF要每秒发送 a ,并且我有Thread.sleep(5000);,则在执行该代码期间将不会获得任何处理程序输出。

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

4

1 回答 1

1

我终于得到了一个肯定的结果,但由于这里很少讨论,我自己的回答会很简短。

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

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

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

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

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

于 2010-08-10T19:53:11.560 回答