`

Java 工具(jmap,jstack)在linux上的源码分析(五) -F 参数的bug

 
阅读更多

当使用jmap,jstack是用-F参数的时候,是通过调用系统调用ptrace来取的寄存器的信息,关于linux下的ptrace实现可以参考我的博客(http://blog.csdn.net/raintungli/article/details/6563867

在jdk6u23版本之前你会发现,当你使用jstack -F的时候 经常在logger 里面 看到错误信息,直接抛出异常,根本无法看到堆栈信息。

Thread 26724: (state = BLOCKED)
Error occurred during stack walking:
sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: get_thread_regs failed for a lwp
at sun.jvm.hotspot.debugger.linux.LinuxDebuggerLocal$LinuxDebuggerLocalWorkerThread.execute(LinuxDebuggerLocal.java:152)
at sun.jvm.hotspot.debugger.....


通过查看源码,最后调用的函数是process_get_lwp_regs /ps_proc.c


无法判断究竟是否是因为没有定义参数PTRACE_GETREGS_REQ,还是因为ptrace的调用参数错误所导致的,这样就必须打开print_debug,查看打印的信息。

通过源码,可以查到print_debug函数是通过环境变量LIBSAPROC_DEBUG来控制

设置

exportLIBSAPROC_DEBUG=1

运行

jstack -F processid

我们能看到错误中多了一行


产生的原因就非常清楚了,bug主要是因为宏定义PTRACE_GETREGS_REQ缺失,查看源码


_LP64 是64位机器的宏定义,而对ptrace的参数PTRACE_GETREGS64,显然Linux kernel 2.6.35里面并没有支持,导致了没有宏定义PTRACE_GETREGS_REQ,这里明显是jvm没有考虑到的情况。

解决办法

a. 因为这是jvm 编译级别的bug,除非你重现修改编译libsaproc.so,覆盖目录/jdk1.6.0_23/jre/lib/amd64

笔者自己编译了这个lib,可以在csdn上下载(http://download.csdn.net/detail/raintungli/4065304),笔者编译的jdk版本是1.6.23 build(19.0)

b. 建议升级jvm到1.6.30版本,该版本已经测试过,已经修复该bug.


后话:


jvm可以在此处更清楚点,不是简单的判断<0,而是在判断<0的时候把errno打印出来,能更容易的判断出是什么原因无法ptrace 上。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics