What are -Xms and -Xmx parameters?
→ No pauses for memory expansion
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
- -Xms = -Xmx in production
- RAMPercentage for containers
- AlwaysPreTouch for stability
- Leave 20-30% for Native Memory
- NMT for monitoring
- Avoid THP with G1
- 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 = -Xmxto prevent resize pauses- Reserved vs Committed:
-Xmxreserves virtual memory;-Xmsimmediately 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 = -Xmxin production? — No Heap expansion pauses; stable GC thresholds; predictable behavior - What happens if
-Xmx30gon 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):
- ”
-Xmxis 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)]]