8.1 การอ้างอิงที่อ่อนแอใน Java
มีการอ้างอิงหลายประเภทใน Java
มีStrongReferenceซึ่งเป็นลิงก์ทั่วไปที่เราสร้างขึ้นทุกวัน
Object object = new Object();//created an object
object = null;//can now be garbage collected
และมีลิงก์ประเภท "พิเศษ" สามประเภท ได้แก่ SoftReference, WeakReference, PhantomReference ในความเป็นจริง มีเพียงความแตกต่างเพียงอย่างเดียวระหว่างลิงก์ทุกประเภท นั่นคือพฤติกรรมของ GC กับอ็อบเจ็กต์ที่พวกเขาอ้างถึง เราจะพูดถึงรายละเอียดเฉพาะของลิงก์แต่ละประเภทในภายหลัง แต่สำหรับตอนนี้ ความรู้ต่อไปนี้ก็เพียงพอแล้ว:
- SoftReferenceคือการอ้างอิงแบบซอฟต์ หาก GC เห็นว่าอ็อบเจ็กต์สามารถเข้าถึงได้ผ่านห่วงโซ่ของการอ้างอิงแบบซอฟต์เท่านั้น ก็จะลบออกจากหน่วยความจำ อาจจะ.
- WeakReference - การอ้างอิงที่อ่อนแอ หาก GC เห็นว่าวัตถุนั้นสามารถเข้าถึงได้ผ่านห่วงโซ่ของการอ้างอิงที่อ่อนแอเท่านั้น ก็จะลบสิ่งนั้นออกจากหน่วยความจำ
- PhantomReferenceเป็นการอ้างอิงแบบหลอน ถ้า GC เห็นว่าออบเจกต์นั้นมีอยู่ผ่านเชนของการอ้างอิงแบบหลอนเท่านั้น ก็จะลบสิ่งนั้นออกจากหน่วยความจำ หลังจากรัน GC มาหลายรอบ
คุณสามารถพูดได้ว่าประเภทลิงก์มีความนุ่มนวลในระดับหนึ่ง:
- ฮาร์ดลิงก์ปกติคือตัวแปรของประเภทการอ้างอิง ไม่ถูกเก็บกวาดโดยคนเก็บขยะก่อนที่จะใช้งานไม่ได้
- ซอฟต์รีเพอเรอร์ อ็อบเจกต์จะไม่ทำให้หน่วยความจำทั้งหมดถูกใช้งาน - รับประกันว่าจะถูกลบก่อนที่จะเกิด OutOfMemoryError อาจเร็วกว่านั้นขึ้นอยู่กับการใช้งานของตัวรวบรวมขยะ
- การอ้างอิงที่อ่อนแอ อ่อนกว่า. ไม่ป้องกันออบเจกต์จากการกำจัด ตัวรวบรวมขยะละเว้นการอ้างอิงดังกล่าว
- PhantomReference . ใช้สำหรับการประมวลผล "ตาย" ของวัตถุ: วัตถุจะพร้อมใช้งานหลังจากการสรุปผลจนกว่าจะมีการรวบรวมขยะ
หากยังไม่ชัดเจนว่าความแตกต่างคืออะไร ไม่ต้องกังวล ทุกอย่างจะเข้าที่ในไม่ช้า รายละเอียดอยู่ในรายละเอียดแล้วรายละเอียดจะตามมา
8.2 WeakReference และ SoftReference ใน Java
ก่อนอื่น มาดูความแตกต่างระหว่างWeakReferenceและSoftReferenceใน Java
กล่าวโดยสรุปก็คือ ตัวรวบรวมขยะจะเพิ่มหน่วยความจำของวัตถุให้ว่าง หากมีเพียงการอ้างอิงที่อ่อนแอเท่านั้นที่ชี้ไปที่วัตถุนั้น หากวัตถุถูกชี้โดย SoftReferences หน่วยความจำจะถูกจัดสรรคืนเมื่อ JVM ต้องการหน่วยความจำอย่างมาก
สิ่งนี้ให้ประโยชน์ที่ชัดเจน กับ SoftReferenceมากกว่าการอ้างอิงที่แข็งแกร่งในบางกรณี ตัวอย่างเช่น มีการใช้ SoftReference เพื่อปรับใช้แคชของแอปพลิเคชัน ดังนั้นสิ่งแรกที่ JVM จะทำคือลบอ็อบเจ็กต์ที่มีเพียง SoftReferences เท่านั้นที่ชี้ไป
WeakReferenceนั้นยอดเยี่ยมสำหรับการจัดเก็บข้อมูลเมตา เช่น การจัดเก็บการอ้างอิงไปยัง ClassLoader หากไม่มีการโหลดคลาส คุณไม่ควรอ้างถึง ClassLoader นี่คือสาเหตุที่ WeakReference ทำให้ตัวรวบรวมขยะสามารถทำงานบน ClassLoader ได้ทันทีที่มีการลบการอ้างอิงที่คาดเดายากล่าสุดออกไป
ตัวอย่าง WeakReference ใน Java:
// some object
Student student = new Student();
// weak reference to it
WeakReference weakStudent = new WeakReference(student);
// now the Student object can be garbage collected
student = null;
ตัวอย่าง SoftReference ใน Java:
// some object
Student student = new Student();
// weak reference to it
SoftReference softStudent = new SoftReference(student)
// now the Student object can be garbage collected
// but this will only happen if the JVM has a strong need for memory
student = null;
8.3 PhantomReference ใน Java
อินสแตนซ์ PhantomReference สร้างขึ้นในลักษณะเดียวกับในตัวอย่าง WeakReference และ SoftReference แต่ไม่ค่อยได้ใช้
PhantomReference สามารถรวบรวมขยะได้หากวัตถุไม่มีการอ้างอิงที่แข็งแกร่ง (แข็งแกร่ง) อ่อนแอ (WeakReference) หรืออ่อนนุ่ม (SoftReference)
คุณสามารถสร้าง Phantom Reference object ได้ดังนี้:
PhantomReference myObjectRef = new PhantomReference(MyObject);
สามารถใช้ PhantomReferenceในสถานการณ์ที่ Finalize() ไม่สมเหตุสมผล ประเภทการอ้างอิงนี้แตกต่างจากประเภทอื่นๆ เนื่องจากไม่ได้ออกแบบมาเพื่อเข้าถึงวัตถุ เป็นสัญญาณว่าวัตถุได้รับการสรุปแล้วและตัวรวบรวมขยะพร้อมที่จะเรียกคืนหน่วยความจำ
ในการทำเช่นนี้ ตัวรวบรวมขยะจะวางไว้ในReferenceQueue พิเศษ สำหรับการประมวลผลเพิ่มเติม ReferenceQueue คือที่วางการอ้างอิงวัตถุเพื่อเพิ่มหน่วยความจำ
การอ้างอิง Phantom เป็นวิธีที่ปลอดภัยในการรู้ว่าวัตถุนั้นถูกลบออกจากหน่วยความจำแล้ว ตัวอย่างเช่น พิจารณาแอปพลิเคชันที่เกี่ยวข้องกับรูปภาพขนาดใหญ่ สมมติว่าเราต้องการโหลดรูปภาพลงในหน่วยความจำเมื่อมีอยู่ในหน่วยความจำแล้ว ซึ่งพร้อมสำหรับการรวบรวมขยะ ในกรณีนี้ เราต้องการรอให้ตัวรวบรวมขยะฆ่าอิมเมจเก่าก่อนที่จะโหลดอิมเมจใหม่ลงในหน่วยความจำ
PhantomReference เป็นทางเลือกที่ยืดหยุ่นและปลอดภัย การอ้างอิงไปยังรูปภาพเก่าจะถูกส่งต่อไปยัง ReferenceQueue หลังจากที่วัตถุรูปภาพเก่าถูกทำลาย เมื่อเรามีลิงค์นี้แล้ว เราสามารถโหลดภาพใหม่ลงในหน่วยความจำได้