OutOfMemoryError: เกินขีด จำกัด ค่าโสหุ้ย GC

1. ภาพรวม

พูดง่ายๆคือ JVM ดูแลการเพิ่มหน่วยความจำเมื่อไม่ได้ใช้วัตถุอีกต่อไป กระบวนการนี้เรียกว่า Garbage Collection (GC)

GC ค่าใช้จ่ายเกินขีด จำกัดข้อผิดพลาดเป็นหนึ่งจากครอบครัวของjava.lang.OutOfMemoryErrorและเป็นข้อบ่งชี้ของทรัพยากร (หน่วยความจำ) อ่อนเพลีย

ในบทความสั้น ๆ นี้เราจะดูสาเหตุที่ทำให้เกิดข้อผิดพลาดjava.lang.OutOfMemoryError: GC Overhead Limit Exceededและจะแก้ไขได้อย่างไร

2. ข้อ จำกัด ค่าโสหุ้ย GC เกินข้อผิดพลาด

OutOfMemoryErrorเป็นคลาสย่อยของjava.lang.VirtualMachineError ; JVM ถูกโยนทิ้งเมื่อพบปัญหาที่เกี่ยวข้องกับการใช้ทรัพยากร โดยเฉพาะอย่างยิ่งข้อผิดพลาดเกิดขึ้นเมื่อ JVM ใช้เวลามากเกินไปในการดำเนินการ Garbage Collectionและสามารถเรียกคืนพื้นที่ฮีปได้เพียงเล็กน้อยเท่านั้น

ตามเอกสาร Java โดยค่าเริ่มต้น JVM ได้รับการกำหนดค่าให้ส่งข้อผิดพลาดนี้หากกระบวนการ Java ใช้เวลามากกว่า 98% ในการทำ GC และเมื่อมีการกู้คืนฮีปเพียงน้อยกว่า 2% ในแต่ละครั้ง กล่าวอีกนัยหนึ่งนั่นหมายความว่าแอปพลิเคชันของเราใช้หน่วยความจำที่มีอยู่เกือบทั้งหมดและ Garbage Collector ใช้เวลามากเกินไปในการทำความสะอาดและล้มเหลวซ้ำ ๆ

ในสถานการณ์เช่นนี้ผู้ใช้พบว่าแอปพลิเคชันทำงานช้ามาก การดำเนินการบางอย่างซึ่งโดยปกติจะเสร็จสมบูรณ์ในหน่วยมิลลิวินาทีต้องใช้เวลามากกว่าจะเสร็จสมบูรณ์ เนื่องจาก CPU ใช้ความจุทั้งหมดสำหรับ Garbage Collection และด้วยเหตุนี้จึงไม่สามารถทำงานอื่นใดได้

3. ข้อผิดพลาดในการดำเนินการ

มาดูโค้ดที่พ่นjava.lang.OutOfMemoryError: GC Overhead Limit Exceeded

ตัวอย่างเช่นเราสามารถบรรลุสิ่งนั้นได้โดยการเพิ่มคู่คีย์ - ค่าในลูปที่ไม่สิ้นสุด:

public class OutOfMemoryGCLimitExceed { public static void addRandomDataToMap() { Map dataMap = new HashMap(); Random r = new Random(); while (true) { dataMap.put(r.nextInt(), String.valueOf(r.nextInt())); } } }

เมื่อเรียกใช้เมธอดนี้โดยมีอาร์กิวเมนต์ JVM เป็น-Xmx100m -XX: + UseParallelGC (ขนาดฮีป Java ถูกตั้งค่าเป็น 100MB และอัลกอริทึม GC คือ ParallelGC) เราจะได้รับข้อผิดพลาดjava.lang.OutOfMemoryError: GC Overhead Limit Exceeded error เพื่อความเข้าใจที่ดีขึ้นเกี่ยวกับอัลกอริธึมการรวบรวมขยะที่แตกต่างกันเราสามารถดูบทแนะนำเกี่ยวกับ Java Garbage Collection Basics ของ Oracle

เราจะได้รับjava.lang.OutOfMemoryError: GC Overhead Limit Exceeded error อย่างรวดเร็วโดยเรียกใช้คำสั่งต่อไปนี้จากรูทของโปรเจ็กต์:

mvn exec:exec

มันก็ควรจะตั้งข้อสังเกตว่าในบางสถานการณ์เราอาจพบข้อผิดพลาดพื้นที่กองก่อนที่จะเผชิญหน้ากับGC ค่าใช้จ่ายเกินขีด จำกัดข้อผิดพลาด

4. การแก้ไขขีด จำกัด ค่าโสหุ้ย GC เกินข้อผิดพลาด

ทางออกที่ดีที่สุดคือการค้นหาปัญหาพื้นฐานของแอปพลิเคชันโดยตรวจสอบรหัสว่ามีหน่วยความจำรั่วหรือไม่

คำถามต่อไปนี้จะต้องได้รับการแก้ไข:

  • อะไรคือวัตถุในแอปพลิเคชันที่ใช้ฮีปส่วนใหญ่
  • วัตถุเหล่านี้ถูกจัดสรรในส่วนใดของซอร์สโค้ด

เรายังสามารถใช้เครื่องมือกราฟิกอัตโนมัติเช่น JConsole ซึ่งช่วยในการตรวจหาปัญหาด้านประสิทธิภาพในโค้ดรวมถึงjava.lang.OutOfMemoryErrors

ทางเลือกสุดท้ายคือการเพิ่มขนาดฮีปโดยการเปลี่ยนการกำหนดค่าการเปิดตัว JVM ตัวอย่างเช่นสิ่งนี้ให้พื้นที่ฮีป 1GB สำหรับแอปพลิเคชัน Java:

java -Xmx1024m com.xyz.TheClassName

อย่างไรก็ตามจะไม่สามารถแก้ปัญหาได้หากมีการรั่วไหลของหน่วยความจำในรหัสแอปพลิเคชันจริง แต่เราจะเลื่อนข้อผิดพลาดออกไป ดังนั้นจึงควรประเมินการใช้งานหน่วยความจำของแอปพลิเคชันใหม่อย่างละเอียดอีกครั้ง

5. สรุป

ในบทช่วยสอนนี้เราได้ตรวจสอบjava.lang.OutOfMemoryError: GC Overhead Limit Exceededและเหตุผลเบื้องหลัง

เช่นเคยซอร์สโค้ดที่เกี่ยวข้องกับบทความนี้สามารถพบได้บน GitHub