0

我们有一个 Java 应用程序,它通过 JNA 调用用 C 编写的 .so 库,因此 Java 应用程序和 C 代码在同一个进程中运行。

我们发现了缓慢的内存泄漏,我们通过JVM堆监视器排除了JVM堆的原因,确认问题存在于JNA或C代码中。

我们发现 jemalloc 可以跟踪内存分配,所以我们使用--prefix=/usr/local --enable-prof选项、设置LD_PRELOAD=/usr/local/lib/libjemalloc.soMALLOC_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 堆内存?如果可能,怎么做?

4

1 回答 1

0

Most JNA memory allocation is done using the Memory class. For example, this line would allocate 1024 bytes of memory using the native malloc().

Memory buffer = new Memory(1024);

Many other JNA classes, such as Structure, use a Memory buffer internally. Other types such as NativeLong also have an appropriate sized allocation.

All of these native memory allocations are eventually released as part of Java's garbage collection process (finalize() calls dispose() which releases the memory).

However, when the allocation is done internally to the native code, there's no way without looking at that source to see where the memory is allocated and freed. This is a common source of leaks, however, if the Java/JNA code invokes a native function which allocates memory, and fails to follow the API instructions on how to release/free that memory when done with it.

Bottom line: you really have to look at the source code and for each native function that operates on memory somewhere, find out whether you are responsible for allocating the memory and passing the buffer (Java/JNA will take care of releasing it) or if the native code itself creates the buffer that it gives you. If it's the latter case, there will always be another method you can/should use to free the buffer.

于 2021-12-07T18:44:11.143 回答