简体   繁体   中英

Finding native memory allocations in a jna application using jemalloc

We have a Java application that invokes a.so library written in C via JNA,so the Java application and C code run in the same process.

We found a slow memory leak, and we have excluded the JVM heap as a cause via JVM heap monitor,confirming that the problem exists in the JNA or C code.

We found jemalloc can track memory allocations,so we install it with --prefix=/usr/local --enable-prof options, and set LD_PRELOAD=/usr/local/lib/libjemalloc.so and MALLOC_CONF=prof_leak:true,lg_prof_sample:17,prof_final:true,prof_prefix:/home/admin/prof_dump/jeprof environment. It generates a dump file,then we use jeprof tool and transform the dump file to a pdf file using jeprof --show_bytes --pdf \ jeprof.* \ >./wdmp-profiling.pdf . The result shown here: memory leak profile

From the figure, we can find many methods invoked about java. But we can't find any information about JNA or C code. From the figure, we found a invoke branch, it only shows hexadecimal address, so we are not sure whether it relates to JNA or C.

We used the perf-map-agent tool and did export symbol mapping, as shown here: symbols mapping

But when we search the hexadecimal address from jeprof result in symbols mapping result, we can't find associated symbols.

Is it possible to find where (C function name or JNA code) native memory is allocated in this case (a Java application invoking C library via JNA), not java heap memory? If it is possible, how?

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM