Memory footprint of a Java process by Andrei Pangin

Devoxx · 44K views · 2019 · 51:40

Open on YouTube

Software performance & optimizationCloud, DevOps & reliabilityC, C++, Rust, Go & systems languagestalk

Why Stack Overflow recommends it

Stack Overflow users link it when explaining why a JVM's RSS or container memory exceeds the heap size and how to track down native memory usage.

Recommended by 3 people across 6 different months, 2018 to 2024.

What it is

A conference talk by Andrei Pangin (JVM expert and author of async-profiler) explaining why a Java process uses far more memory than -Xmx suggests. It covers the JVM structures that add to the footprint, real native memory leak cases, and tools for analysing allocations.

What people said

Strong rec Juraj Martinka · 2020-06 · Stack Overflow · on “Accounting for Java memory consumption”

There's more than you see on the NewRelic's non-heap memory usage graph. E.g. there are also Thread stacks which can occupy up to 1MB per thread. There's a JVM feature called Native Memory Tracking that you can use to track some of the non-heap memory usage. There can still be native allocations that aren't tracked at all. I suggest you look at these excellent resources from @apangin: Java using much more memory than heap size (or size correctly Docker memory limit) [LINK] Memory footprint of a Java process by Andrei Pangin: [this video]

Strong rec Juraj Martinka · 2020-06 · Stack Overflow · on “Active Memory of the system is continuously increasing”

Active memory simply means "pages that have been accessed recently" and isn't a terribly interesting measure on its own (see [LINK] for more information) It's much more useful to track the RSS (as reported by ps et al) and then JVM-specific portions of the memory like the heap, thread stacks, code cache, metaspace, etc - for a thorough overview I recommend these excellent resources: Java using much more memory than heap size (or size correctly Docker memory limit) [LINK] Memory footprint of a Java process by Andrei Pangin: [this video]

Recommends apangin · 2020-01 · Stack Overflow · on “Understanding Jeprofile output”

In your jemalloc output, JVM_FindSignal is accounted for 97% of allocations. This can't be true, since JVM_FindSignal does not allocate anything. This must be the result of the issue that JVM has no debug symbols [LINK] . Install the package with JDK debug symbols as descibed in this answer [LINK] , or use JDK with built-in debug symbols, e.g. Liberica JDK [LINK] . jemalloc does not know anything about Java methods. It can't translate the addresses in JIT compiled code to Java method names. Hence so many addresses (hex numbers) in your jemalloc output. There is a Java profiler, async-profiler [LINK] , that can trace native memory allocations down to Java code, and show Java stack traces as F

Recommends apangin · 2020-05 · Stack Overflow · on “How to Determine Whether OpenJDK Installed with Debugging Symbols”

java executable is just a simple launcher [LINK] . You won't find JVM symbols there. To see if JVM has debug symbols, check libjvm.so instead: nm /usr/lib/jvm/jre/lib/amd64/server/libjvm.so My ultimate goal is to load a malloc profiler alongside my server and try to trace the native memory allocations. In this case, if the calls are traced back to JVM, I need to know which method is getting called. Well, if you'd started with this question, you wouldn't have fallen into XY problem [LINK] trap. Even with JVM debug symbols, native memory profilers (e.g. jemalloc) cannot show Java methods. They simply don't know how to unwind Java stack, so the traces will likely break at some random hex addres

Recommends apangin · 2020-06 · Stack Overflow · on “Native memory consumed by JVM vs java process total memory usage”

NativeMemoryTracking may report less committed memory than the actual Resident Set Size (RSS) of a process for multiple reasons. NMT counts only certain JVM structures. It does not count memory mapped files (including loaded .jar files), nor memory allocated by libraries other than libjvm . Even native memory allocated by the standard class library (i.e. libjava ) is not shown in NMT report. When something allocates memory with a standard system allocator ( malloc ) and then releases it, this memory isn't always returned back to the OS. The system allocator may keep released memory in a pool for future reuse, but from the OS perspective this memory is considered used (and thus included in RS

Recommends apangin · 2020-09 · Stack Overflow · on “jemalloc and JVM_FindSignal”

It turns out that openjdk-8-dbg package installs files with debug symbols into /usr/lib/debug/.build-id jeprof looks for debug symbols in /usr/lib/debug/{FULL_SO_PATH} So, it's a combination of a bug in jeprof that does not parse .note.gnu.build-id section, and a problem of the dbg package that does not include full path symlinks to debug libraries. To work around this, you may create the corresponding symlink manually: 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 (the file names are taken from gdb output) However, even when jeprof is able to read debug symbols, this doesn't often

Recommends apangin · 2022-03 · Stack Overflow · on “Java memory off heap inside container”

should I use nonHeap+heap to calculate the total usage by my application. No. Total physical memory used by a Java process includes many things not counted by the JVM. See this answer [LINK] and this presentation [this video] for details. My main doubt is about "freePhysicalMemorySizeMB", this value variates a lot between containers even when the committed memories (heap+nonHeap) have the same value . Just don't look at getFreePhysicalMemorySize() . This value is rarely useful. It does not take into account page cache [LINK] and various reclaimable OS structures that can be automatically freed when the application requests more memory. The most meaningful measure of the process' memory usage is R

Recommends Michael · 2023-08 · Stack Overflow · on “Why Java NMT commited memory could be much less then RSS? (if there is no swap)”

I would suggest this video: [this video] He explains parts of the JVM which consume memory, only one of which is the heap. He works through some examples of how to diagnose issues.

Cites apangin · 2018-12 · Stack Overflow · on “Java using much more memory than heap size (or size correctly Docker memory limit)”

Virtual memory used by a Java process extends far beyond just Java Heap. You know, JVM includes many subsytems: Garbage Collector, Class Loading, JIT compilers etc., and all these subsystems require certain amount of RAM to function. JVM is not the only consumer of RAM. Native libraries (including standard Java Class Library) may also allocate native memory. And this won't be even visible to Native Memory Tracking. Java application itself can also use off-heap memory by means of direct ByteBuffers. So what takes memory in a Java process? JVM parts (mostly shown by Native Memory Tracking) 1. Java Heap The most obvious part. This is where Java objects live. Heap takes up to -Xmx amount of memo

Cites Eugene · 2020-02 · Stack Overflow · on “Java process consuming 90% of swap space”

Your Java process is made not only from heap memory, watch this for a good example [this video] . Now, you say that you have 28GB of RAM, out of which you allocate 20GB for heap only . Not only do you reserve virtual memory, but you also commit it, via AlwaysPreTouch (I now doubt you even understand what this does). So your OS, maps 20GB of RAM to your process (simplified explanation). Even if you see that only 50% is occupied, the garbage collector that you use - does not release memory back to the OS, so the entire 20GC are always occupied and can not be re-used by some other process. As such, it is pointless to measure or monitor the heap. Your process fails with Native memory allocation (mmap