นี่คือตัวอย่างที่แตกต่างกันเล็กน้อยตัวอย่างหนึ่งที่มีฟิลด์ประเภทการอ้างอิงขั้นสุดท้ายแทนที่จะเป็นตัวแปรโลคัลประเภทค่าสุดท้าย:
public class MyClass {
public final MyOtherObject obj;
}
ทุกครั้งที่คุณสร้างอินสแตนซ์ของ MyClass คุณจะต้องสร้างการอ้างอิงขาออกไปยังอินสแตนซ์ MyOtherObject และ GC จะต้องไปตามลิงก์นั้นเพื่อค้นหาวัตถุที่มีชีวิต
JVM ใช้อัลกอริทึม GC แบบกวาดเครื่องหมายซึ่งต้องตรวจสอบการอ้างอิงสดทั้งหมดในตำแหน่ง "root" ของ GC (เช่นเดียวกับวัตถุทั้งหมดใน call stack ปัจจุบัน) วัตถุที่มีชีวิตแต่ละชิ้นจะถูก "ทำเครื่องหมาย" ว่ามีชีวิตและวัตถุใด ๆ ที่อ้างถึงโดยวัตถุที่มีชีวิตจะถูกทำเครื่องหมายว่ามีชีวิต
หลังจากเสร็จสิ้นขั้นตอนการทำเครื่องหมาย GC จะกวาดผ่านฮีปทำให้หน่วยความจำว่างสำหรับวัตถุที่ไม่มีเครื่องหมายทั้งหมด (และกระชับหน่วยความจำสำหรับวัตถุที่มีชีวิตที่เหลืออยู่)
นอกจากนี้สิ่งสำคัญคือต้องทราบว่าหน่วยความจำฮีป Java แบ่งออกเป็น "คนรุ่นใหม่" และ "รุ่นเก่า" เริ่มแรกวัตถุทั้งหมดจะถูกจัดสรรในคนรุ่นใหม่ (บางครั้งเรียกว่า "เรือนเพาะชำ") เนื่องจากวัตถุส่วนใหญ่มีอายุการใช้งานสั้น GC จึงมีความก้าวร้าวมากขึ้นในการกำจัดขยะล่าสุดจากคนรุ่นใหม่ หากวัตถุมีชีวิตอยู่ในวงจรการสะสมของคนรุ่นใหม่วัตถุนั้นจะถูกเคลื่อนย้ายไปสู่คนรุ่นเก่า (บางครั้งเรียกว่า "รุ่นอายุ") ซึ่งมีการประมวลผลน้อยกว่า
ผมจะบอกว่า "ไม่" โมดิเฟอร์ "ขั้นสุดท้าย" ไม่ได้ช่วยให้ GC ลดภาระงานลง "
ในความคิดของฉันกลยุทธ์ที่ดีที่สุดในการเพิ่มประสิทธิภาพการจัดการหน่วยความจำของคุณใน Java คือการกำจัดการอ้างอิงปลอมโดยเร็วที่สุด คุณสามารถทำได้โดยกำหนด "null" ให้กับการอ้างอิงวัตถุทันทีที่คุณใช้งานเสร็จ
หรือที่ดีกว่านั้นคือลดขนาดของขอบเขตการประกาศแต่ละรายการ ตัวอย่างเช่นหากคุณประกาศวัตถุที่จุดเริ่มต้นของเมธอด 1000 บรรทัดและถ้าวัตถุยังมีชีวิตอยู่จนกระทั่งใกล้ขอบเขตของเมธอดนั้น (วงเล็บปีกกาปิดสุดท้าย) วัตถุนั้นอาจมีชีวิตอยู่ได้นานกว่านั้น จำเป็น
หากคุณใช้วิธีการเล็ก ๆ โดยมีโค้ดเพียงไม่กี่บรรทัดอ็อบเจ็กต์ที่ประกาศภายในเมธอดนั้นจะหลุดออกจากขอบเขตได้เร็วขึ้นและ GC จะสามารถทำงานส่วนใหญ่ได้ภายในประสิทธิภาพที่มากขึ้น คนรุ่นใหม่. คุณไม่ต้องการให้วัตถุถูกย้ายไปสู่คนรุ่นเก่าเว้นแต่จำเป็นจริงๆ