代码之家  ›  专栏  ›  技术社区  ›  user400348

如何正确地编写调用AsyncgetCallTrace的sigprof处理程序?

  •  3
  • user400348  · 技术社区  · 15 年前

    我正在编写一个短而简单的剖析器(在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/profileing-with-jvmtijvmpi-sigprof-and.html。

    这个博客缺少的是在信号处理程序中实际调用函数的代码(作者假设读者可以自己做这件事)。我正在寻求帮助来做这件事。我不知道如何以及在何处创建结构asgct_calltrace(以及内部结构asgct_callframe),如上述forte.cpp文件中所定义的。结构asgct_calltrace是传递给asyncgetcalltrace的参数之一,因此我确实需要创建它,但我不知道如何获取其字段的正确值:jnienv*env_id、jint num_frames和jvmpi_callframe 框架。此外,我不知道第三个参数传递给AsyncgetCallTrace的是什么(void u上下文)应该是吗?

    以上问题是我的主要问题。但是,我面临的其他问题包括: [1]sigprof似乎不是由计时器按指定的时间间隔精确地提升的,而是稍微降低了一点频率。也就是说,如果我将计时器设置为每秒发送一个sigprof(1秒,0 usec),那么在5秒钟的运行中,我得到的sigprof处理程序输出少于5个(通常是1-3个) [2 ] SIGPROF处理程序输出在Java代码中的线程睡眠期间根本不出现。因此,如果每秒钟发送一个sigprof,并且我有thread.sleep(5000);,那么在代码执行期间,我将不会得到任何处理程序输出。

    任何帮助都将不胜感激。其他细节(以及部分代码和样本输出)将根据要求公布。

    谢谢!

    1 回复  |  直到 14 年前
        1
  •  1
  •   user400348    14 年前

    我最终得到了一个积极的结果,但由于很少有讨论在这里产生,我自己的答案将是简短的。

    asgct_calltrace结构(以及基础asgct_callframe数组)可以简单地在信号处理程序中声明,因此仅存在堆栈: asgct_calltrace跟踪; JNIENV*Env; 全局_vm_指针->AttachCurrentThread((void**)&env,空); trace.env_id=env; trace.num_帧=0; asgct_callframe存储[25]; trace.frames=存储;

    以下是UContext: UContext_t UContext; getContext(&ucContext);

    然后电话是: asyncgetCalltrace(&trace,25&ucontext);

    我确信在这个过程中还有一些其他的细微差别需要处理,但我并没有真正记录下来。我不确定是否可以公开我当前的全部代码,它成功地异步请求并以固定的间隔获得任何Java程序的堆栈跟踪。但是,如果有人对同一个问题感兴趣,或者固守在同一个问题上,我现在可以帮上忙了(我想)。

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

    推荐文章