Fundamentals 5 min read

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.

ITFLY8 Architecture Home
ITFLY8 Architecture Home
ITFLY8 Architecture Home
Why Java Processes Show 50GB+ VIRT Memory and How to Control It

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.

VIRT usage screenshot
VIRT usage screenshot

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Virtual MemoryglibcMALLOC_ARENA_MAXVIRT
ITFLY8 Architecture Home
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.