JVM Native Memory Areas

JVM native memory is memory obtained outside the Java heap for runtime components and execution infrastructure. Important areas include metaspace, the code cache, thread stacks, and other JVM-internal structures.

The Java heap stores objects managed by the garbage collector, but a JVM process needs additional memory to operate. This native memory can hold runtime metadata, compiled machine code, thread stacks, and internal JVM structures. It is part of the process's memory footprint even though it is not Java heap space.

Metaspace stores metadata about loaded classes and is allocated from native memory. Unlike the older permanent generation used by older HotSpot configurations, metaspace is not part of the Java heap. Its usage can grow as classes are loaded, although class unloading can reclaim eligible metadata.

Each Java thread requires a native thread stack for method execution, including local variables and call frames. The configured stack size therefore contributes to native memory usage, and creating many threads can substantially increase the process footprint.

The JVM also maintains a code cache containing generated native machine code produced by the JIT compiler. Other native allocations include JVM data structures, synchronization structures, garbage-collection bookkeeping, and memory used by native libraries. Consequently, a process can encounter native-memory pressure even when heap usage appears healthy.

Key points

Interview questions

What is JVM native memory?

JVM native memory is memory used by the JVM outside the Java heap. It supports components such as class metadata, thread stacks, compiled code, and internal runtime structures. This memory still contributes to the JVM process's total memory consumption. Therefore, monitoring only heap usage does not give the complete memory picture.

What is stored in metaspace?

Metaspace contains metadata associated with classes loaded by the JVM. It is allocated from native memory rather than from the Java heap. As classes are loaded, metaspace usage can increase, and eligible class metadata can be reclaimed when classes are unloaded.

How do Java threads affect native memory usage?

Each Java thread needs a native stack for its execution state, including call frames and local variables. The stack size and number of threads therefore affect native memory consumption. A service that creates a very large number of threads can exhaust process memory even if its Java heap is relatively small.

Why might a JVM be killed for memory usage when heap usage looks normal?

The process consumes memory beyond the Java heap, including metaspace, thread stacks, the code cache, JVM internal structures, and native-library allocations. A container or operating-system limit applies to the process's overall memory rather than simply the Java heap. Consequently, a modest heap does not guarantee that the process stays below its memory limit. Diagnosing this situation requires examining the JVM's non-heap and native allocations as well as the heap.