jemalloc 和 JVM_FindSignal

jemalloc and JVM_FindSignal

正如在这个问题中已经回答的那样:

jemalloc 报告来自 JVM_FindSignal 的泄漏与缺少调试符号有关。我当然安装了调试符号,请参阅:

rbs42@rbs42-VirtualBox:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/amd64/server$ gdb libjvm.so -ex 'info address UseG1GC'
GNU gdb (Ubuntu 9.1-0ubuntu1) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from libjvm.so...
Reading symbols from /usr/lib/debug/.build-id/16/240e0172c3fc0dd6e974325c8ad1d93723ccac.debug...
(No debugging symbols found in /usr/lib/debug/.build-id/16/240e0172c3fc0dd6e974325c8ad1d93723ccac.debug)
Installing openjdk unwinder
Traceback (most recent call last):
  File "/usr/share/gdb/auto-load/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/libjvm.so-gdb.py", line 52, in <module>
    class Types(object):
  File "/usr/share/gdb/auto-load/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/libjvm.so-gdb.py", line 66, in Types
    nmethodp_t = gdb.lookup_type('nmethod').pointer()
gdb.error: No type named nmethod.
Symbol "UseG1GC" is at 0xd189b2 in a file compiled without debugging.

我的 jeprof 输出仍然如下所示:

rbs42@rbs42-VirtualBox:/media/rbs42/data/Gebos/RBS42/run/sms50$ jeprof --show_bytes /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java jeprof.22104.0.f.heap 
Using local file /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java.
Using local file jeprof.22104.0.f.heap.
Welcome to jeprof!  For help, type 'help'.
(jeprof) top
Total: 33502504 B
20958503  62.6%  62.6% 21342909  63.7% JVM_FindSignal
 8388608  25.0%  87.6%  8388608  25.0% SNX11B1A
 1481379   4.4%  92.0%  1481379   4.4% inflate
 1151253   3.4%  95.5%  1151253   3.4% Java_java_util_zip_ZipFile_getZipMessage
  426303   1.3%  96.7%   426303   1.3% SNE00B1A
  404065   1.2%  97.9%   404065   1.2% inflateInit2_
  253077   0.8%  98.7% 20393297  60.9% SUNWprivate_1.1
  176271   0.5%  99.2%   176271   0.5% std::__throw_ios_failure
  131713   0.4%  99.6%   131713   0.4% _dl_new_object
  131328   0.4% 100.0%   131328   0.4% _dl_check_map_versions
(jeprof) 

还有什么要考虑的吗?

原来是

  1. openjdk-8-dbg 软件包将带有调试符号的文件安装到 /usr/lib/debug/.build-id
  2. jeprof/usr/lib/debug/{FULL_SO_PATH}
  3. 中查找调试符号

因此,它是 jeprof 中不解析 .note.gnu.build-id 部分的错误,以及不包含调试库的完整路径符号链接的 dbg 包问题的组合。

要解决此问题,您可以手动创建相应的符号链接:

ln -s /usr/lib/debug/.build-id/16/240e0172c3fc0dd6e974325c8ad1d93723ccac.debug /usr/lib/debug/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/libjvm.so

(文件名取自 gdb 输出)


然而,即使 jeprof 能够读取调试符号,这对于 Java 应用程序通常也无济于事。问题是 jemalloc 不知道如何展开 Java 堆栈。有关示例,请参阅 this presentation

考虑尝试 async-profiler that can show mixed Java+native stacks. Profiling malloc, mprotect and mmap calls with async-profiler can be helpful in finding native memory leaks in Java applications. See this answer 了解详情。

这是一个 jeprof 补丁,可以更智能地查找调试符号。它基于@apangin 的回答。

https://github.com/jemalloc/jemalloc/pull/2059/files