【问题标题】:jemalloc and JVM_FindSignaljemalloc 和 JVM_FindSignal
【发布时间】:2020-09-23 20:51:46
【问题描述】:

正如在这个问题中已经回答的那样: JVM_FindSignal function continuously allocates native memory

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) 

还有什么要考虑的吗?

【问题讨论】:

    标签: memory jvm java-native-interface jemalloc


    【解决方案1】:

    原来是这样

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

    因此,这是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,它可以显示混合的 Java+native 堆栈。使用 async-profiler 分析 mallocmprotectmmap 调用有助于发现 Java 应用程序中的本机内存泄漏。详情请见this answer

    【讨论】:

    • 非常感谢。你是对的,尽管当用 os::malloc 替换 JVM_FindSignal 时调用堆栈现在看起来并没有更好。实际上,我昨天通过 VisualVM 报告的数据类型跟踪它,发现了我的主要泄漏。对于 JVM 在不同的 JNI 调用中返回的大量字节数组,我缺少一个 DeleteLocalRef。肯定会研究 async-profiler。
    • 超级有用的评论@apangin,tysm!!我试图找到 ln 映射的一个技巧:为 eu-readelf 安装 elfutils,然后编辑 jeprof(因为它只是一个 Perl 脚本),并在 return undef 之前在 DebuggingLibrary 方法中添加一行日志记录,例如:@ 987654336@ 产生如下输出:no debug symbols found for /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/libjava.so, Build ID: dd2ed27070b86465905be1fe49eb110418f18503
    • 我起初也错过了示例中的 16/ 是构建 ID 的前 2 位数字。在这里解释:sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-30
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      • 1970-01-01
      • 2018-11-23
      • 2020-05-11
      • 1970-01-01
      相关资源
      最近更新 更多