How Does a Jvm Process Allocate Its Memory

How does a JVM process allocate its memory?

Approach:

You may want to use Java HotSpot Native Memory Tracking (NMT).

This may give you an exact list of memory allocated by the JVM, splitted up into the different areas heap, classes, threads, code, GC, compiler, internal, symbols, memory tracking, pooled free chunks, and unknown.

Usage:

  • You can start your application with -XX:NativeMemoryTracking=summary.

  • Observations of the current heap can be done with jcmd <pid> VM.native_memory summary.

Where to find jcmd / pid:

On a default OpedJDK installation on Ubuntu this can be found at /usr/bin/jcmd.

By just running jcmd without any parameter, you get a list of running Java applications.

user@pc:~$ /usr/bin/jcmd
5169 Main <-- 5169 is the pid

Output:

You will then receive a complete overview over your heap, looking something like the following:

Total: reserved=664192KB, committed=253120KB <--- total memory tracked by Native Memory Tracking

  • Java Heap (reserved=516096KB, committed=204800KB) <--- Java Heap

    (mmap: reserved=516096KB, committed=204800KB)

  • Class (reserved=6568KB, committed=4140KB) <--- class metadata

    (classes #665) <--- number of loaded classes

    (malloc=424KB, #1000) <--- malloc'd memory, #number of malloc

    (mmap: reserved=6144KB, committed=3716KB)

  • Thread (reserved=6868KB, committed=6868KB)
    (thread #15) <--- number of threads

    (stack: reserved=6780KB, committed=6780KB) <--- memory used by thread stacks

    (malloc=27KB, #66)

    (arena=61KB, #30) <--- resource and handle areas

  • Code (reserved=102414KB, committed=6314KB)

    (malloc=2574KB, #74316)

    (mmap: reserved=99840KB, committed=3740KB)

  • GC (reserved=26154KB, committed=24938KB)

    (malloc=486KB, #110)

    (mmap: reserved=25668KB, committed=24452KB)

  • Compiler (reserved=106KB, committed=106KB)

    (malloc=7KB, #90)

    (arena=99KB, #3)

  • Internal (reserved=586KB, committed=554KB)

    (malloc=554KB, #1677)

    (mmap: reserved=32KB, committed=0KB)

  • Symbol (reserved=906KB, committed=906KB)

    (malloc=514KB, #2736)

    (arena=392KB, #1)

  • Memory Tracking (reserved=3184KB, committed=3184KB)

    (malloc=3184KB, #300)

  • Pooled Free Chunks (reserved=1276KB, committed=1276KB)

    (malloc=1276KB)

  • Unknown (reserved=33KB, committed=33KB)

    (arena=33KB, #1)

This gives a detailed overview of the different memory areas used by the JVM, and also shows the reserved and commited memory.

I don't know of a technique that gives you a more detailed memory consumption list.

Further reading:

You can also use -XX:NativeMemoryTracking=detail in combination with further jcmd commands. A more detailed explaination can be found at Java Platform, Standard Edition Troubleshooting Guide - 2.6 The jcmd Utility. You can check possible commands via "jcmd <pid> help"

Understanding JVM Memory Allocation and Java Out of Memory: Heap Space


How does the JVM actually allocate memory for itself?

For the heap it allocate one large continuous region of memory of the maximum size. Initially this is virtual memory however, over time it becomes real memory for the portions which are used, under control of the OS

How does this relate to how the OS communicates available memory to the JVM?

The JVM has no idea about free memory in the OS.

Or more generally, how does memory allocation for any process actually work?

In general it uses malloc and free.

How does virtual memory come into play?

Initially virtual memory is allocated and this turns into real memory as used. This is normal for any process.

Let's say you have a system with 32GB of physical memory and you allocate all 32GB to your Java process.

You can't. The OS need some memory and there will be memory for other purposes. Even within the JVM the heap is only a portion of the memory used. If you have 32 GB of memory I suggest as 24 GB heap max.

Let's say that your process actually consumes all 32GB of memory,

Say you have 48 GB and you start a process which uses 32 GB of main memory.

how can we enforce the process to use virtual memory instead of running into OOM exceptions?

The application uses virtual memory right from the start. You cannot make the heap too large because if it starts swapping your machine (not just your application) will become unusable.

You can use more memory than you have physical by using off heap memory, carefully. However managed memory must be in physical memory so if you need a 32 GB heap, buy 64 GB of main memory.

Java heap inside or outside jvm memory?

There is a lot to discuss on this question. I always like the articles from IBM since it contains very good information. For this specific question, here is an excerpt.

From The native and Java heaps article on IBM:

The JVM maintains two memory areas, the Java™ heap, and the native (or
system) heap. These two heaps have different purposes and are
maintained by different mechanisms.

The Java heap contains the instances of Java objects and is often
referred to as 'the heap'. It is the Java heap that is maintained by
Garbage Collection, and it is the Java heap that is changed by the
command-line heap settings. The Java heap is allocated using mmap, or
shmat if large page support is requested. The maximum size of the Java
heap is preallocated during JVM startup as one contiguous area, even
if the minimum heap size setting is lower. This allocation allows the
artificial heap size limit imposed by the minimum heap size setting to
move toward the actual heap size limit with heap expansion.

The native, or system heap, is allocated by using the underlying
malloc and free mechanisms of the operating system, and is used for
the underlying implementation of particular Java objects; for example:

  • Motif objects required by AWT and Swing
  • Buffers for data compression routines, which are the memory space that the Java Class Libraries require to read or write compressed data
    like .zip or .jar files.
  • Malloc allocations by application JNI code
  • Compiled code generated by the Just In Time (JIT) Compiler
  • Threads to map to Java threads

Hope it helps you understand.

Find the memory allocated by the JVM

there is a command that comes with the JRE called jps which you can use to see all the running java processes. using jps with -v gives you the launch parameters of each process.

terminal

You can see here the launch parameters which will tell you the memory usage of each process.

This command should run also on Windows, just replace the terminal with a command prompt.

What does it mean that the memory requested by JVM from the OS has to be contiguous ?


  1. JVM allocates memory for different purposes. Of course, this is not just a single chunk of memory. Some JVM structures need to occupy a contiguous chunk, other do not.

  2. If we talk about Java Heap in HotSpot JVM - yes, it is a contiguous range of virtual address space.

  3. The contiguous virtual memory does not have to be backed by contiguous physical memory. Page table is responsible for translating virtual addresses to physical, and it makes possible to map the contiguous virtual address range to fragmented physical pages even after swapping etc.

  4. While it's usually not a problem to find a contiguous virtual address range for Java heap or another JVM structure on a 64-bit system, this can be a real issue on a 32-bit system.

  5. You are right, OS memory overcommitment settings may cause mmap or mprotect call to fail, if the process' total virtual memory size exceeds a threshold.



Related Topics



Leave a reply



Submit