Why Java Processes Show 50GB+ VIRT Memory and How to Control It
An investigation reveals that Java 8 processes can report virtual memory usage exceeding 50 GB due to extensive address space allocation by glibc’s arena mechanism, not actual physical memory, and explains how environment variables like MALLOC_ARENA_MAX can limit this VIRT growth.
1. Phenomenon
Recently the virtual memory (VIRT) of a Java 8 process on a production server reached over 50 GB, as shown in the screenshot below.
2. Ineffective -Xmx
The first instinct is to limit heap size with Java’s -Xmx option, but adjusting it has little effect on the reported VIRT size, prompting further investigation.
3. What is VIRT
Modern operating systems separate virtual address space from physical memory. On a 64‑bit OS the maximum virtual address space is 16 EB (≈180 billion GB). Therefore a machine with only 16 GB RAM can still reserve several terabytes of address space.
void *mem = mmap(0, 4ul * 1024ul * 1024ul * 1024ul * 1024ul,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
-1, 0);When MAP_NORESERVE is used, the kernel does not require actual physical memory or swap for the mapping, so the above call shows 4096 GB of VIRT even though it is impossible to allocate that much physical memory.
4. Why so much address space
Running pmap -x on the Java process reveals many 64 MB anonymous mappings. This is caused by glibc’s “arena” feature introduced in version 2.10, which allocates a private arena for each thread to accelerate multithreaded allocation. CentOS 6/7 ships glibc 2.12/2.17, so the issue appears there.
p2 = (char *)mmap(aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE,
MAP_NORESERVE | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);Only a small portion of the reserved address space is backed by physical memory:
mprotect(p2, size, PROT_READ | PROT_WRITE);In a multithreaded program, dozens of 64 MB arenas can be allocated. The number of arenas can be limited with the environment variable MALLOC_ARENA_MAX, which defaults to 128 on 64‑bit systems.
5. Java’s peculiarity
Java manages its own heap, reducing the number of calls to glibc’s allocator. Since Java 8, the permanent generation has been replaced by Metaspace, which resides in native memory. Each thread allocates a small Metaspace and its own arena (64 MB), causing a large amount of virtual address space to be reserved.
6. Conclusion
High VIRT values are caused by excessive address‑space reservation, not actual memory usage.
In most cases the VIRT size can be ignored because the system has a huge virtual address space (up to 16 EB).
If you need to control VIRT, set MALLOC_ARENA_MAX (e.g., Hadoop recommends a value of 4) as YARN monitors VIRT for resource usage.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITFLY8 Architecture Home
ITFLY8 Architecture Home - focused on architecture knowledge sharing and exchange, covering project management and product design. Includes large-scale distributed website architecture (high performance, high availability, caching, message queues...), design patterns, architecture patterns, big data, project management (SCRUM, PMP, Prince2), product design, and more.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
