แนวพฤติกรรมของคนเก็บขยะ (การเรียกคืนหน่วยความจำ)
โปรแกรมเมอร์ Java ไม่จำเป็นต้องตรวจสอบการจัดสรรหน่วยความจำเนื่องจากตัวรวบรวมขยะจัดการหน่วยความจำโดยอัตโนมัติ Garbage Collector รันโดย Java Virtual Machine (JVM) ตัวรวบรวมขยะเป็นกระบวนการที่มีลำดับความสำคัญต่ำที่ทำงานเป็นระยะๆ และเพิ่มหน่วยความจำที่ใช้โดยอ็อบเจ็กต์ที่ไม่จำเป็นอีกต่อไป JVM ที่แตกต่างกันมีอัลกอริธึมการรวบรวมขยะที่แตกต่างกัน มีอัลกอริธึมที่ใช้อยู่หลายอย่าง เช่น อัลกอริธึมการนับอ้างอิง หรืออัลกอริธึมมาร์กอัปและการขูด
เรียกใช้ตัวรวบรวมขยะใน Java
โดยทั่วไป JVM จะรันตัวรวบรวมขยะเมื่อหน่วยความจำว่างเหลือน้อย แต่การทำงานของตัวรวบรวมขยะไม่ได้รับประกันว่าจะมีหน่วยความจำว่างเพียงพอเสมอไป หากมีหน่วยความจำไม่เพียงพอแม้จะกู้คืนแล้ว JVM จะส่งข้อยกเว้น OutOfMemoryError โปรดทราบว่า JVM ต้องรันตัวรวบรวมขยะอย่างน้อยหนึ่งครั้งก่อนที่จะส่งข้อยกเว้น คุณสามารถขอให้ตัวรวบรวมขยะทำงานใน Java ได้ แต่คุณไม่สามารถบังคับการกระทำนี้ได้
ร้องขอให้ดำเนินการเก็บขยะ
หากต้องการส่งคำขอ คุณสามารถเรียกวิธีใดวิธีหนึ่งต่อไปนี้:
System.gc()
Runtime.getRuntime().gc()
ความเหมาะสมในการเดินรถเก็บขยะ
วัตถุจะต้องถูกกำจัดเมื่อไม่มีอยู่ในสตรีมที่มีชีวิตอีกต่อไป วัตถุอาจถูกกำจัดในกรณีต่างๆ:
- หากตัวแปรประเภทการอ้างอิงที่อ้างอิงถึงออบเจ็กต์ถูกตั้งค่าเป็น "0" จะต้องกำจัดออบเจ็กต์นั้นหากไม่มีการอ้างอิงอื่น ๆ
- ถ้าตัวแปรของประเภทการอ้างอิงที่อ้างอิงถึงวัตถุถูกสร้างขึ้นเพื่ออ้างอิงถึงวัตถุอื่น จะต้องกำจัดวัตถุนั้นหากไม่มีการอ้างอิงอื่น ๆ
- ออบเจ็กต์ที่สร้างขึ้นภายในเครื่องในวิธีการจะถูกยกเลิกเมื่อออกจากวิธีการ เว้นแต่ว่าจะถูกส่งออกจากวิธีการนั้น (นั่นคือ ส่งคืนหรือส่งออกเป็นข้อยกเว้น)
- วัตถุที่อ้างอิงถึงกันอาจถูกกำจัด หากไม่มีรายการใดอยู่ในเธรดสด
ลองดูตัวอย่าง:
public class TestGC
{
public static void main(String [] args)
{
Object o1 = new Integer(3);
Object o2 = new String("Tutorial");
o1 = o2;
o2 = null;
}
}
ในตัวอย่างนี้
Integer
วัตถุ (จำนวนเต็ม) ที่เดิมอ้างอิงโดย o1 สามารถกำจัดทิ้งหลังบรรทัดที่ 3 ได้ เนื่องจากตอนนี้ o1 อ้างถึงวัตถุ
String
(สตริง) แม้ว่า o2 จะถูกสร้างขึ้นเพื่ออ้างถึงค่า null แต่วัตถุ
String
(สตริง) จะไม่สามารถรีไซเคิลได้เนื่องจาก o1 อ้างถึงวัตถุนั้น
การสรุปผล
เทคโนโลยี Java ช่วยให้คุณสามารถใช้วิธีการ
finalize()
(สิ้นสุด) เพื่อทำการล้างข้อมูลที่จำเป็นก่อนที่ตัวรวบรวมขยะจะดึงอ็อบเจ็กต์จากหน่วยความจำ วิธีการนี้ถูกเรียกบนวัตถุโดยตัวรวบรวมขยะเมื่อตัวรวบรวมขยะกำหนดว่าไม่มีการอ้างอิงไปยังวัตถุอีกต่อไป สิ่งนี้อธิบายไว้ในคลาส
Object
ซึ่งหมายความว่าคลาสทั้งหมดสืบทอดมา คลาสย่อยแทนที่วิธี
finalize()
การปลดปล่อยตัวเองจากทรัพยากรระบบหรือสำหรับการล้างข้อมูลอื่น:
protected void finalize() throws Throwable
หากข้อยกเว้นที่ไม่ได้ลงทะเบียนถูกส่งออกไปโดย method
finalize()
ข้อยกเว้นจะถูกละเว้นและการสิ้นสุดของวัตถุนั้นจะหยุดลง วิธีการนี้
finalize()
จะถูกเรียกใช้เพียงครั้งเดียวในช่วงอายุของออบเจ็กต์ เป็นไปได้ที่จะใช้วิธีการ
finalize()
กับวัตถุใดๆ เพื่อป้องกันวัตถุนั้นจากการกำจัด แต่ในกรณีนี้ ตัวรวบรวมขยะจะไม่เปิดใช้งาน
finalize()
สำหรับวัตถุนี้ อีกต่อไป วิธีการนี้
finalize()
จะถูกเรียกใช้หนึ่งครั้งเสมอก่อนที่วัตถุจะถูกรวบรวมขยะ อย่างไรก็ตาม มีความเป็นไปได้ที่วิธีการนี้
finalize()
จะไม่ถูกเปิดใช้งานสำหรับวัตถุที่กำหนดตลอดระยะเวลาที่มีอยู่ เนื่องจากอาจไม่สามารถกำจัดทิ้งได้
สรุป
ในส่วนนี้ เรามาดูกระบวนการรวบรวมขยะซึ่งเป็นเทคนิคการจัดการหน่วยความจำในภาษา Java ไม่สามารถบังคับเก็บขยะได้ เราได้เรียนรู้เกี่ยวกับวิธีการต่างๆ เพื่อทำให้วัตถุมีสิทธิ์รีไซเคิล และเรียนรู้ว่า
finalize()
มีการเรียกใช้วิธีการดังกล่าวก่อนที่ผู้รวบรวมขยะจะเรียกคืนวัตถุ
ออกกำลังกาย
คำถาม: จะต้องกำจัดสิ่งของกี่ชิ้นหลังจากบรรทัดที่ 7
public class TutorialGC
{
public static void main(String [] args)
{
Object a = new Integer(100);
Object b = new Long(100);
Object c = new String("100");
a = null;
a = c;
c = b;
b = a;
}
}
ตัวเลือกคำตอบ: A. 0 B. 1 C. 2 D. 3 E. ไม่สามารถรวบรวมรหัสได้
ตัวเลือกที่ถูกต้อง: B
คำอธิบาย:จากวัตถุทั้งสามที่สร้างขึ้นในบรรทัดที่ 1, 2 และ 3 เฉพาะวัตถุเท่านั้น
Integer
ที่ต้องถูกกำจัดที่ ท้ายบรรทัด 7 การอ้างอิงตัวแปร a ซึ่งเดิมอ้างอิงถึงวัตถุ
Integer
อ้างอิงวัตถุ
String
บนบรรทัด 5 ดังนั้น
Integer
วัตถุจะต้องถูกกำจัดหลังจากบรรทัด 5 เนื่องจากไม่มีตัวแปรที่อ้างอิงถึงวัตถุนั้น ตัวแปร
b
และ
c
อ้างถึงวัตถุ
String
และ
Long
วัตถุในบรรทัดที่ 6 และ 7 ดังนั้นจึงไม่สามารถรีไซเคิลได้
GO TO FULL VERSION