What is Metaspace (or PermGen)?
4. Cache proxies and scripts 5. TraceClassLoading for debugging
Junior Level
Metaspace — memory area (outside Heap) where Java stores class metadata.
Metadata includes: class name, method names and signatures, fields, annotations, constant pool, vtable/itable (virtual method tables).
Simple analogy: If Heap is a wardrobe with clothes, then Metaspace is a catalog with clothing descriptions.
What’s stored:
- Class information
- Methods and their byte-code
- Constant Pool
PermGen → Metaspace (Java 8):
- PermGen: fixed size inside Heap → OOM
- Metaspace: OOM happens less often, but is still common with dynamic class generation (Spring, Hibernate, Groovy, CGLIB)
Middle Level
PermGen vs Metaspace
| Characteristic | PermGen | Metaspace |
|---|---|---|
| Location | Inside Heap | Native Memory |
| Size | Fixed | Dynamic |
| OOM | Frequent | Rare |
What causes Metaspace growth
1. Many classes in application
2. Dynamic generation (Spring proxies, CGLIB)
3. ClassLoader leaks
4. Scripting engines (Groovy, JavaScript)
Configuration
-XX:MetaspaceSize=256m # Threshold for first GC
-XX:MaxMetaspaceSize=512m # Maximum (mandatory!)
ClassLoader Leaks
Classes live as long as their ClassLoader lives
→ If ClassLoader is not GC'd → all classes remain
Causes:
- ThreadLocal holds object from ClassLoader
- Static field references application class
- JDBC driver in DriverManager
Senior Level
Compressed Class Space
Separate area in Metaspace for Klass structures
→ Default 1 GB
→ -XX:CompressedClassSpaceSize to change
Klass = C++ mirror of Java class
→ InstanceKlass (vtable, itable)
→ Method Metadata
→ Constant Pool
High-Water Mark Mechanism
1. Metaspace grows → reaches MetaspaceSize
2. Full GC → attempt to unload ClassLoaders
3. If not enough → expands and raises threshold
4. Repeats
Problem: series of Full GCs at application startup
Solution: MetaspaceSize = typical consumption after warmup
Elastic Metaspace (Java 16+)
JEP 387: improved memory return to OS
→ Before: large Chunks → fragmentation
→ Now: small blocks → aggressive return
Diagnostics
jcmd <pid> VM.metaspace # Detailed report
jstat -gc <pid> 1000 # MU column
-Xlog:class+load=info # Class loading
Best Practices
- MaxMetaspaceSize — mandatory in Docker. Don’t set too close to actual consumption — this causes frequent Full GC. Keep at least 30-50% margin.
- MetaspaceSize = consumption after warmup
- Monitor ClassLoader leaks
- Cache proxies and scripts
- TraceClassLoading for debugging
Senior Summary
- Metaspace = native memory for class metadata
- High-Water Mark = dynamic expansion
- ClassLoader Leaks = main cause of OOM
- Compressed Class Space = 1 GB limit
- Elastic Metaspace (Java 16+) = better memory return
Interview Cheat Sheet
Must know:
- Metaspace (Java 8+) stores class metadata: class name, methods, fields, annotations, constant pool, vtable/itable
- PermGen (before Java 7): inside Heap, fixed size → frequent OOM; Metaspace: native memory, dynamic growth
- ClassLoader Leak — main cause of Metaspace OOM; classes live as long as their ClassLoader lives
- High-Water Mark: Metaspace grows → Full GC → if little unloaded → expansion → series of Full GCs at startup
-XX:MaxMetaspaceSizeis mandatory in Docker;-XX:MetaspaceSize= typical consumption after warmup- Elastic Metaspace (Java 16+, JEP 387): small blocks instead of large Chunks → aggressive memory return to OS
- Compressed Class Space: separate area ~1 GB for Klass structures (C++ mirrors of Java classes)
Common follow-up questions:
- What causes Metaspace growth? — Dynamic class generation (Spring/CGLIB/Hibernate), Groovy/JavaScript scripts, ClassLoader leaks
- Why does MetaspaceSize cause Full GC at startup? — When threshold is reached, JVM triggers Full GC to unload ClassLoaders; if threshold is too low — series of Full GCs
- How to diagnose ClassLoader leak? —
jcmd <pid> VM.metaspace,-Xlog:class+load=info, compare class loading/unloading - Why shouldn’t MaxMetaspaceSize be set too tight? — Keep at least 30-50% margin above actual consumption; otherwise frequent Full GC
Red flags (DO NOT say):
- “Metaspace is inside Heap” — Metaspace is in native memory (outside Heap)
- “PermGen and Metaspace are the same” — PermGen is fixed inside Heap, Metaspace is dynamic in native memory
- “Metaspace OOM is impossible” — happens with dynamic class generation and ClassLoader leaks
Related topics:
- [[7. How can a memory leak occur in Java]]
- [[8. What are generations in GC]]
- [[20. What types of OutOfMemoryError exist]]
- [[6. What is a memory leak in Java]]
- [[2. What is stored in Heap]]