Question 11 · Section 3

What is Metaspace (or PermGen)?

4. Cache proxies and scripts 5. TraceClassLoading for debugging

Language versions: English Russian Ukrainian

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

  1. MaxMetaspaceSize — mandatory in Docker. Don’t set too close to actual consumption — this causes frequent Full GC. Keep at least 30-50% margin.
  2. MetaspaceSize = consumption after warmup
  3. Monitor ClassLoader leaks
  4. Cache proxies and scripts
  5. 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:MaxMetaspaceSize is 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]]