Question 18 · Section 3

What are -Xms and -Xmx parameters?

→ No pauses for memory expansion

Language versions: English Russian Ukrainian

Junior Level

-Xms and -Xmx — parameters for configuring Java Heap memory size.

-Xms — initial Heap size (how much memory to take at startup) -Xmx — maximum Heap size (won’t take more than this)

Example:

java -Xms512m -Xmx2g MyApp
# Startup: 512 MB
# Maximum: 2 GB

In most production scenarios: -Xms = -Xmx (prevents resizing overhead). Exceptions: CLI utilities (small -Xms for fast startup), memory-constrained environments. → No pauses for memory expansion


Middle Level

Reserved vs Committed

-Xmx4g:
  → JVM reserves 4 GB of virtual memory
  → Physical memory allocated as needed

-Xms4g:
  → 4 GB of physical memory allocated immediately

Why -Xms = -Xmx

If -Xms < -Xmx:
  1. Application grows → needs larger Heap
  2. JVM tries to avoid expansion: first runs GC to free space in current Heap.
     In modern GCs (G1), this is usually Young/Mixed GC, not Full GC.
     But if GC didn't help → JVM requests more memory from OS.
  3. Pause!
  4. Expansion → system call

If -Xms = -Xmx:
  → No resize pauses
  → Stable GC thresholds
  → Predictable behavior

Docker/Kubernetes

# Modern approach (Java 11+):
-XX:InitialRAMPercentage=75.0
-XX:MaxRAMPercentage=75.0

# JVM reads container limit
# → 75% of container RAM = Heap
# → Flexible: change limit in YAML → Heap changes

AlwaysPreTouch

-XX:+AlwaysPreTouch

# On startup: physically allocate all pages
# → Startup takes longer
# → No micro-delays on first access
# → Guaranteed that memory is allocated

Senior Level

Transparent Huge Pages (THP)

Linux: Huge Pages = 2 MB instead of 4 KB
  → Fewer TLB misses
  → +5-10% performance

Problem: THP conflicts with G1
  → Long GC pauses

Solution:
  1. Disable THP at kernel level
  2. Use static Huge Pages:
     -XX:+UseLargePages

Native Memory = not just Heap

RSS (total process memory) =
  Heap (-Xmx)
  + Metaspace
  + Code Cache
  + Thread Stacks (-Xss × threads)
  + Direct Buffers
  + GC Overhead

→ -Xmx30g on 32 GB server = OOM Killer!
→ Leave 20-30% for Native Memory

NMT (Native Memory Tracking)

-XX:NativeMemoryTracking=summary

jcmd <pid> VM.native_memory summary

# Shows:
# Java Heap: 30 GB
# Class: 50 MB
# Thread: 100 MB
# Code: 80 MB
# GC: 200 MB
# Internal: 50 MB
# ...

Best Practices

  1. -Xms = -Xmx in production
  2. RAMPercentage for containers
  3. AlwaysPreTouch for stability
  4. Leave 20-30% for Native Memory
  5. NMT for monitoring
  6. Avoid THP with G1
  7. Don’t set -Xmx too close to RAM

Senior Summary

  • -Xms = -Xmx = no resize pauses
  • RAMPercentage = flexibility in containers
  • AlwaysPreTouch = no page fault delays
  • RSS > -Xmx = account for Native Memory
  • NMT = full memory monitoring
  • THP = be careful with G1
  • OOM Killer = if -Xmx too close to RAM

Interview Cheat Sheet

Must know:

  • -Xms — initial Heap size, -Xmx — maximum; in production -Xms = -Xmx to prevent resize pauses
  • Reserved vs Committed: -Xmx reserves virtual memory; -Xms immediately allocates physical memory
  • On Heap expansion (-Xms < -Xmx): JVM first runs GC → if not helped → system call to OS → pause
  • Docker/Kubernetes: -XX:InitialRAMPercentage=75.0 / -XX:MaxRAMPercentage=75.0 — JVM reads container limit
  • AlwaysPreTouch: on startup, physically allocate all pages → longer startup, but no micro-delays on first access
  • RSS = Heap + Metaspace + Code Cache + Thread Stacks + Direct Buffers + GC Overhead; leave 20-30% RAM for Native Memory
  • Transparent Huge Pages (THP): +5-10% performance, but conflicts with G1 → long GC pauses

Common follow-up questions:

  • Why -Xms = -Xmx in production? — No Heap expansion pauses; stable GC thresholds; predictable behavior
  • What happens if -Xmx30g on a 32 GB server? — OOM Killer kills the process: RSS > 32 GB (Metaspace + Stacks + Code Cache another 2-4 GB)
  • Why AlwaysPreTouch? — Prevents page fault delays on first page access; guarantees memory is actually allocated
  • Why does THP conflict with G1? — G1 uses different-sized regions; THP (2 MB pages) causes fragmentation → long GC pauses

Red flags (DO NOT say):

  • -Xmx is the entire process memory” — RSS is significantly larger: Metaspace, Stacks, Code Cache, Direct Buffers
  • “THP always improves performance” — conflicts with G1; disable or use static Huge Pages
  • “In container, JVM automatically uses full limit” — without RAMPercentage, JVM sees the host, not the container (Java 8 without patches)

Related topics:

  • [[1. What is the difference between Heap and Stack]]
  • [[2. What is stored in Heap]]
  • [[19. What happens on OutOfMemoryError]]
  • [[22. What tools help analyze memory]]
  • [[11. What is Metaspace (or PermGen)]]