【发布时间】:2021-12-06 09:34:29
【问题描述】:
我们有一个 Java 应用程序,它通过 JNA 调用用 C 编写的 .so 库,因此 Java 应用程序和 C 代码在同一个进程中运行。
我们发现了一个缓慢的内存泄漏,我们通过JVM堆监视器排除了JVM堆的原因,确认问题存在于JNA或C代码中。
我们发现jemalloc可以跟踪内存分配,所以我们安装了--prefix=/usr/local --enable-prof选项,并设置了LD_PRELOAD=/usr/local/lib/libjemalloc.so和MALLOC_CONF=prof_leak:true,lg_prof_sample:17,prof_final:true,prof_prefix:/home/admin/prof_dump/jeprof环境。它会生成一个转储文件,然后我们使用 jeprof 工具将转储文件转换为使用jeprof --show_bytes --pdf \ jeprof.* \ > ./wdmp-profiling.pdf 的pdf 文件。此处显示的结果:memory leak profile
从图中,我们可以发现调用了很多关于java的方法。但是我们找不到任何关于 JNA 或 C 代码的信息。从图中我们发现了一个invoke分支,它只显示了16进制地址,所以不知道是JNA还是C。
我们使用perf-map-agent工具,做了导出符号映射,如下图:symbols mapping
但是当我们从 jeprof 结果中搜索符号映射结果的十六进制地址时,我们找不到关联的符号。
在这种情况下(通过 JNA 调用 C 库的 Java 应用程序)是否可以找到(C 函数名称或 JNA 代码)本机内存分配的位置,而不是 Java 堆内存?如果可以,怎么做?
【问题讨论】: