加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

在进行特定系统调用时记录java堆栈跟踪?

发布时间:2021-01-08 02:31:19 所属栏目:Linux 来源:网络整理
导读:上下文:我正在研究一个基于Java的网络服务器,它意外地泄漏了管道.它每隔几天就达到40,000个文件描述符的限制并死掉.在死亡之前在服务器上使用lsof表明它被管道堵塞.管道连接到自身,而不是另一个过程. 代码库的任何部分都不会创建或使用管道 我们可以看到.

上下文:我正在研究一个基于Java的网络服务器,它意外地泄漏了管道.它每隔几天就达到40,000个文件描述符的限制并死掉.在死亡之前在服务器上使用lsof表明它被管道堵塞.管道连接到自身,而不是另一个过程.

代码库的任何部分都不会创建或使用管道 – 我们可以看到.

一些旧版本的JVM创建了&在创建套接字时泄漏了一个管道,但是这个在java 1.7.0_75上展示,我认为它不会遭受这个bug.

我的问题是:使用现代Linux工具链(例如perf)可以在调用pipe(2)系统调用时对进程进行快照 – 我认为这是管道创建的唯一方法.此外,是否有可能从中检索Java堆栈跟踪?

鉴于此信息,应该可以回答“谁在创建管道,为什么?”这一问题.

最佳答案 在java 1.7.0_75(或pre-java 8 update 60)上,您只能从事件调用堆栈上的perf获取有限信息,因为堆栈将被截断(参见下文).

您可以在sys调用管道上获取系统范围的跟踪点事件,并使用以下perf命令或类似命令关闭.

perf record -e 'syscalls:sys_enter_pipe*' -e 'syscalls:sys_enter_close' -ag -- sleep 10

要获得完整堆栈:

>在生产中运行之前在测试系统上进行测试.
>安装Java 8 update 60或更高版本
>使用-XX:PreserveFramePointer运行java以避免截断的堆栈
>可选(因为它不是生产就绪代码)从Github安装并运行perf-map-agent来解析Java JIT符号以供perf使用
>发生问题时运行上述“perf记录”或类似记录
>运行“perf script”以输出跟踪点事件和关联的堆栈跟踪

截断的堆栈将是底部没有线程启动功能的堆栈,例如:

java 19575 [018] 10600910.346655: syscalls:sys_enter_pipe: fildes: 0x7f353b9f7f80
        7f3809cff0b7 __pipe (/usr/lib64/libc-2.17.so)
        7f37f59aecb9 [unknown] (/tmp/perf-19375.map)
        7f37f5e83150 [unknown] (/tmp/perf-19375.map)
    edb4639ef8034082 [unknown] ([unknown])

完整堆栈可能看起来更像:

java 21553 [009] 10601254.522385: syscalls:sys_enter_pipe: fildes: 0x7f545322f340
        7f54527180b7 __pipe (/usr/lib64/libc-2.17.so)
        7f543d007760 [unknown] (/tmp/perf-21552.map)
        7f543d0007a7 [unknown] (/tmp/perf-21552.map)
        7f5451ce1be6 JavaCalls::call_helper (/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so)
        7f5451fe7b27 Reflection::invoke (/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so)
        7f5451feb237 Reflection::invoke_method (/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so)
        7f5451d705fb JVM_InvokeMethod (/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so)
        7f543da669ed [unknown] (/tmp/perf-21552.map)
        7f543d0007a7 [unknown] (/tmp/perf-21552.map)
        7f5451ce1be6 JavaCalls::call_helper (/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so)
        7f5451d23182 jni_invoke_static (/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so)
        7f5451d3fb8a jni_CallStaticVoidMethod (/usr/java/jdk1.8.0_60/jre/lib/amd64/server/libjvm.so)
        7f5452bfcbcc JavaMain (/usr/java/jdk1.8.0_60/jre/lib/amd64/jli/libjli.so)
        7f5452e12df5 start_thread (/usr/lib64/libpthread-2.17.so)

使用perf-map-agent运行以允许perf将JITted [unknown]函数解析为java方法.

关于如何做到这一点还有其他各种指南,包括Brendan Gregg的工作http://techblog.netflix.com/2015/07/java-in-flames.html

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读