Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

ความแตกต่างระหว่าง PermGen Space และ Metaspace ใน Java

Java 8 ย้าย **PermGen (Permanent Generation)** ไปเป็น **Metaspace** - การเปลี่ยนแปลงสำคัญใน Memory Management

ตารางเปรียบเทียบ

ลำดับหัวข้อPermGen (Java 7 และก่อน)Metaspace (Java 8+)
1พื้นฐานMemory area สำหรับ Class metadata (class definitions, static variables, bytecode, methods)แทนที่ PermGen - เก็บ Class metadata เช่นเดียวกันแต่ใน Native Memory
2Locationส่วนหนึ่งของ **Heap Memory****Native Memory (OS Memory)** - แยกจาก Heap
3Default Size64 MB (32-bit) / 82 MB (64-bit)Auto-expand (ไม่มี default max)
4Max Size Config-XX:MaxPermSize=256m-XX:MaxMetaspaceSize=256m
5Initial Size Config-XX:PermSize=64m-XX:MetaspaceSize=64m (initial high-water mark)
6GC BehaviorFull GC ถ้าเต็ม (ช้า, STW ยาว)Metaspace GC แยกต่างหาก (เร็วกว่า, concurrent)
7Class Unloadingยาก/นادرة (ต้อง Full GC)รองรับดีกว่า (Class unloading ทำได้ง่ายขึ้น)
8OOM Errorjava.lang.OutOfMemoryError: PermGen spacejava.lang.OutOfMemoryError: Metaspace
9String InterningString pool อยู่ใน PermGenString pool ย้ายไป Heap (Java 7+)

ทำไมต้องเปลี่ยนเป็น Metaspace?

  • ✅ **ไม่ต้อง tuning PermSize** - Auto-expand ตามความต้องการ
  • ✅ **ไม่มี OOM: PermGen** - เพราะใช้ Native Memory (จำกัดโดย OS/RAM)
  • ✅ **Class Unloading ดีกว่า** - เหมาะกับ Dynamic class loading (OSGi, Hot reload, JSP)
  • ✅ **แยกจาก Heap** - Heap ใช้สำหรับ Object instances เท่านั้น
  • ✅ **Performance** - GC metadata แยกจาก object GC

JVM Flags สำคัญ

FlagคำอธิบายDefault
-XX:MetaspaceSizeInitial high-water mark (trigger first GC)Platform-dependent (~21MB)
-XX:MaxMetaspaceSizeMax size (unlimited = ไม่จำกัด)Unlimited
-XX:MinMetaspaceFreeRatioMin % free after GC (expand ถ้าน้อยกว่า)40
-XX:MaxMetaspaceFreeRatioMax % free after GC (shrink ถ้ามากกว่า)70
-XX:+UseCompressedClassPointersCompress class pointers (ประหยัด memory)Enabled (64-bit)
-XX:CompressedClassSpaceSizeSize สำหรับ compressed class pointers1GB

Monitoring Metaspace

# Command line
jcmd  VM.metaspace

# JConsole / VisualVM / JMC - ดูใน Memory tab

# Programmatic
MemoryPoolMXBean metaspace = ManagementFactory.getMemoryPoolMXBeans().stream()
    .filter(mp -> mp.getName().contains("Metaspace"))
    .findFirst().orElse(null);
    
if (metaspace != null) {
    MemoryUsage usage = metaspace.getUsage();
    System.out.println("Used: " + usage.getUsed() / 1024 / 1024 + " MB");
    System.out.println("Max: " + (usage.getMax() == -1 ? "Unlimited" : usage.getMax() / 1024 / 1024 + " MB"));
}

Troubleshooting Metaspace OOM

  1. Class Loader Leak - ClassLoaders ไม่ถูก GC (common ใน Tomcat redeploy, OSGi)
  2. Dynamic Class Generation - CGLIB, ByteBuddy, JSP compilation, Groovy scripts
  3. Large number of classes - Microservices รวมกัน, Fat jars

แก้ไข

  • ตั้ง -XX:MaxMetaspaceSize=512m (ป้องกันกิน RAM หมด)
  • ใช้ -Xlog:gc+metaspace=debug (Java 9+) trace Metaspace GC
  • แก้ Class Loader Leak (ปิด ThreadLocal, DriverManager, Loggers ก่อน redeploy)

สรุป

PermGen = Fixed-size Heap area (Legacy, Java 7-)
Metaspace = Dynamic Native Memory (Modern, Java 8+)

Metaspace ลดปัญหา OOM และ tuning complexity แต่ต้องระวัง Native Memory exhaustion