Memory Leak คืออะไร?
ใน Java มี Garbage Collector (GC) จัดการหน่วยความจำอัตโนมัติ แต่ Memory Leak เกิดขึ้นเมื่อ:
- ออบเจกต์ยังมี reference ชี้อยู่ (ไม่ได้ถูกปล่อย)
- แต่โปรแกรมไม่ได้ใช้ออบเจกต์นั้นต่อไปแล้ว
- GC จึงไม่สามารถเก็บขยะออบเจกต์นั้นได้
- สะสมมากพอ →
OutOfMemoryError: Java heap space
ตัวอย่าง: Heap Exhaustion
import java.util.Vector;
public class Demo {
public static void main(String[] args) {
Vector
ผลลัพธ์
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.base/java.util.Vector.<init>(Vector.java:142)
at Demo.main(Demo.java:7)
คำอธิบาย
พยายามจัดสรร Vector ขนาด 784 ล้าน elements → เกิน heap size → JVM โยน OutOfMemoryError ก่อนถึงบรรทัดสุดท้าย
สาเหตุ Memory Leak จริงๆ (Common Causes)
1. Static Collections เก็บออบเจกต์ไม่เคย clear
// อันตราย! static Listcache = new ArrayList<>(); public void add(Object o) { cache.add(o); } // ไม่มีการลบออกเลย
2. Listener/Callback ไม่ถูก deregister
button.addActionListener(listener); // ต้องมี button.removeActionListener(listener) เมื่อไม่ใช้แล้ว
3. ThreadLocal ไม่ถูก remove
ThreadLocaltl = new ThreadLocal<>(); tl.set(conn); // ต้อง tl.remove() เมื่อจบการใช้งาน มิฉะะ leak ใน thread pool
4. Cache ไม่มีขนาดจำกัด (unbounded)
// ใช้ LinkedHashMap + removeEldestEntry หรือ Caffeine/Guava Cache แทน
การป้องกันและแก้ไข
- ตั้งค่า
-Xmxให้เพียงพอ แต่ไม่ใช่แก้ root cause - ใช้ WeakReference / SoftReference สำหรับ cache
- ปิด resource (try-with-resources): Stream, Connection, File
- ตั้งค่า
-XX:+HeapDumpOnOutOfMemoryErrorเพื่อวิเคราะห์ heap dump - ใช้ Profiler: VisualVM, JProfiler, YourKit, Java Mission Control
- Code review หา static collections, listeners, ThreadLocal ที่ไม่ clean up
เครื่องมือวินิจฉัย
# Heap dump เมื่อ OOM java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap.hprof MyApp # วิเคราะห์ด้วย jhat หรือ Eclipse MAT jhat /tmp/heap.hprof