我们有一个 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 工具将转储文件转换为 pdf 文件jeprof --show_bytes --pdf \ jeprof.* \ > ./wdmp-profiling.pdf
。此处显示的结果:内存泄漏配置文件
从图中我们可以发现java调用的方法很多。但是我们找不到任何关于 JNA 或 C 代码的信息。从图中我们发现了一个invoke分支,它只显示了16进制地址,所以我们不确定它是否与JNA或C有关。
我们使用了perf-map-agent工具并做了导出符号映射,如下所示:符号映射
但是当我们从 jeprof 结果中搜索符号映射结果的十六进制地址时,我们找不到相关的符号。
在这种情况下(通过 JNA 调用 C 库的 Java 应用程序)是否可以找到(C 函数名称或 JNA 代码)本机内存分配的位置,而不是 Java 堆内存?如果可能,怎么做?