gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 00:56:17 24 4
gpt4 key购买 nike

上下文:我正在开发一个基于 Java 的网络服务器,该服务器意外泄漏了管道。每隔几天它就会达到 40,000 个文件描述符的限制并死掉。在服务器死亡之前使用 lsof 显示它被管道阻塞。管道连接到自身,而不是另一个进程。

我们可以看到,代码库中没有任何部分创建或使用管道。

一些旧版本的 JVM 在创建套接字时创建并泄漏了一个管道,但是这在 java 1.7.0_75 上表现出来,我相信它不会遇到这个错误。

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

根据这些信息,应该可以回答“谁在创建管道,为什么?”这个问题

最佳答案

在 java 1.7.0_75(或 java 8 update 60 之前的版本)上,您只能从 perf 获得有关事件调用堆栈的有限信息,因为堆栈将被截断(见下文)。

您可以使用以下 perf 命令或类似命令在系统调用管道和关闭时获取系统范围的跟踪点事件。

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

获取完整堆栈:

  1. 在生产环境中运行之前在测试系统上进行测试。
  2. 安装 Java 8 update 60 或更高版本
  3. 使用 -XX:+PreserveFramePointer 运行 java 以避免截断堆栈
  4. 可选(因为它不是生产就绪代码)从 Github 安装并运行 perf-map-agent 以解析 Java JIT 符号以供 perf 使用
  5. 出现问题时运行上述“perf record”或类似命令
  6. 运行“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 [未知] 函数解析为 java 方法。

关于如何执行此操作的各种其他指南包括 Brendan Gregg 的作品 http://techblog.netflix.com/2015/07/java-in-flames.html

关于java - 在进行特定系统调用时记录 java 堆栈跟踪?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38264181/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com