Garbage Collection (GC) ใน Java คือกระบวนการจัดการหน่วยความจำอัตโนมัติที่ตรวจสอบอ็อบเจ็กต์ที่ไม่มีการใช้งานแล้ว และลบออกจากหน่วยความจำเพื่อเปิดพื้นที่ให้กับอ็อบเจ็กต์ใหม่ ทำให้นักพัฒนาไม่ต้องเขียนโค้ดจัดการ Memory เอง ต่างจากภาษา C หรือ C++ ที่ต้องจัดการ Allocation และ Deallocation ด้วยตัวเอง
Garbage Collection คืออะไร
Garbage Collection เป็นฟีเจอร์ที่ทำให้ภาษา Java โดดเด่น เพราะช่วยจัดการหน่วยความจำให้โดยอัตโนมัติ ระบบ Garbage Collector จะทำงานอยู่เบื้องหลังของ Java Virtual Machine (JVM) คอยตรวจสอบอ็อบเจ็กต์ที่ไม่มีตัวแปรหรือโครงสร้างข้อมูลอ้างถึงอยู่ แล้วทำการลบออกจากหน่วยความจำ
สำหรับองค์กรที่รันแอปพลิเคชัน Java บนเซิร์ฟเวอร์ หรือ ระบบ VPS การเข้าใจหลักการทำงานของ GC จะช่วยให้ปรับแต่งประสิทธิภาพได้ดียิ่งขึ้น
การแบ่งพื้นที่หน่วยความจำแบบ Generational
JVM แบ่งพื้นที่ Heap Memory ออกเป็นส่วนต่าง ๆ ตามอายุของอ็อบเจ็กต์
- Young Generation เป็นพื้นที่สำหรับอ็อบเจ็กต์ที่เพิ่งถูกสร้างขึ้นมาใหม่ อ็อบเจ็กต์ส่วนใหญ่จะถูกเก็บกวาดที่นี่เพราะมักมีอายุสั้น แบ่งย่อยเป็น Eden Space และ Survivor Space
- Old Generation หรือ Tenured Generation สำหรับอ็อบเจ็กต์ที่ผ่านการ GC มาหลายรอบแล้วยังถูกใช้งานอยู่ การ GC ในพื้นที่นี้ใช้เวลานานกว่า
- Metaspace เก็บ Metadata ของคลาส แทนที่ PermGen ที่ถูกยกเลิกไปตั้งแต่ Java 8
กระบวนการ Mark and Sweep
วิธีการหลักที่ GC ใช้คือ Mark and Sweep ในขั้นตอน Mark ระบบจะทำเครื่องหมายอ็อบเจ็กต์ที่ยังใช้งาน จากนั้นในขั้นตอน Sweep จะลบอ็อบเจ็กต์ที่ไม่ได้ถูกทำเครื่องหมาย บาง Algorithm จะมีขั้นตอน Compact เพิ่มเพื่อจัดเรียงหน่วยความจำ ลดปัญหา Fragmentation
ประเภทของ Garbage Collector
Serial GC
เหมาะสำหรับแอปพลิเคชันขนาดเล็กที่ทำงานบน CPU เดียว ใช้ Thread เดียวในการทำ GC แอปพลิเคชันต้องหยุดทำงานชั่วคราวระหว่าง GC ทำงาน
Parallel GC
ใช้หลาย Thread ในการทำ GC พร้อมกัน เร็วกว่า Serial GC เหมาะกับแอปพลิเคชันที่ต้องการ Throughput สูง
G1 GC (Garbage First)
ออกแบบมาเพื่อลด Pause Time โดยแบ่ง Heap ออกเป็น Region เล็ก ๆ และเก็บ Region ที่มีขยะมากที่สุดก่อน เหมาะสำหรับแอปพลิเคชันที่ต้องการ Response Time ที่ดีและมี Heap ขนาดใหญ่
ZGC และ Shenandoah
GC รุ่นใหม่ที่มี Pause Time ต่ำมากในระดับมิลลิวินาที แม้จะทำงานกับ Heap ขนาดหลาย TB เหมาะสำหรับแอปพลิเคชันที่ต้องการ Low Latency อย่างแท้จริง
การปรับแต่ง Garbage Collection
การตั้งค่า Heap Size
พารามิเตอร์ -Xms กำหนดขนาด Heap เริ่มต้น และ -Xmx กำหนดขนาด Heap สูงสุด การตั้งค่าทั้งสองให้เท่ากันจะช่วยลด Overhead จากการขยายและหดตัวของ Heap
การเลือก GC Algorithm
ใช้ Flag -XX:+UseG1GC สำหรับ G1 GC หรือ -XX:+UseZGC สำหรับ ZGC ถ้าต้องการ Throughput สูงให้เลือก Parallel GC ถ้าต้องการ Low Latency ให้เลือก ZGC หรือ G1
การวิเคราะห์ GC Logs
เปิดใช้งาน GC Logging ด้วย -Xlog:gc เพื่อวิเคราะห์พฤติกรรมของ GC ข้อมูลจาก Log ช่วยให้เข้าใจว่า GC ทำงานบ่อยแค่ไหนและใช้เวลานานเท่าไหร่
ปัญหาที่พบบ่อย
Memory Leak ใน Java
แม้จะมี GC แต่ Memory Leak ก็ยังเกิดขึ้นได้จากการเก็บ Reference ไว้โดยไม่จำเป็น เช่น เก็บอ็อบเจ็กต์ใน Static Collection โดยไม่เคยลบออก หรือลืม Close Resource
GC Pause Time นานเกินไป
ถ้า GC ใช้เวลานานจะทำให้แอปพลิเคชันหยุดตอบสนอง แก้ได้โดยเลือก GC ที่เหมาะสม ปรับขนาด Heap และลดการสร้างอ็อบเจ็กต์ที่ไม่จำเป็น
Out of Memory Error
เกิดเมื่อ GC ไม่สามารถเคลียร์หน่วยความจำได้เพียงพอ มักเกิดจาก Heap ขนาดเล็กเกินไปหรือมี Memory Leak การเลือกเซิร์ฟเวอร์ที่มี RAM เพียงพอเป็นสิ่งสำคัญสำหรับแอปพลิเคชัน Java ที่ต้องรองรับภาระงานหนัก
คำถามที่พบบ่อย
สามารถบังคับให้ GC ทำงานได้หรือไม่
สามารถเรียก System.gc() ได้ แต่ JVM ไม่จำเป็นต้องทำตาม เป็นเพียงคำแนะนำเท่านั้น ในทางปฏิบัติไม่แนะนำให้เรียก System.gc() เพราะ JVM จัดการ GC ได้ดีกว่าการบังคับด้วยตัวเอง
GC ทำให้แอปพลิเคชันช้าลงหรือไม่
GC ต้องหยุดการทำงานของแอปพลิเคชันชั่วคราว (Stop-the-World Pause) แต่ GC รุ่นใหม่อย่าง ZGC ลด Pause Time ลงเหลือระดับมิลลิวินาที ทำให้แทบไม่ส่งผลต่อผู้ใช้
ควรเลือก GC ตัวไหนดี
สำหรับแอปพลิเคชันทั่วไป G1 GC เป็นตัวเลือกที่ดีและเป็นค่าเริ่มต้นตั้งแต่ Java 9 สำหรับแอปพลิเคชันที่ต้องการ Low Latency ให้ใช้ ZGC สำหรับงาน Batch Processing ที่เน้น Throughput ให้ใช้ Parallel GC
Java มี Memory Leak ได้จริงหรือ
ได้ แม้จะมี GC แต่ถ้าโค้ดเก็บ Reference ไว้โดยไม่จำเป็น GC จะไม่สามารถเก็บกวาดอ็อบเจ็กต์เหล่านั้นได้ ตัวอย่างที่พบบ่อยคือ Static Collection ที่เพิ่มอ็อบเจ็กต์เรื่อย ๆ โดยไม่เคยลบ
รันแอปพลิเคชัน Java อย่างมีประสิทธิภาพกับ DriteStudio
สำหรับองค์กรที่ต้องการรันแอปพลิเคชัน Java อย่างมีประสิทธิภาพ DriteStudio มีบริการ VPS และ Dedicated Server ที่มีทรัพยากรเพียงพอสำหรับปรับแต่ง JVM ได้อย่างอิสระ พร้อมระบบ Hosting ที่รองรับ Java Application ติดต่อทีมงานเพื่อเลือกแพลนที่เหมาะกับความต้องการ