ฉันได้อ่านบทความนี้เกี่ยวกับหัวข้อ แต่ฉันไม่เข้าใจจริงๆ โปรดให้คำแนะนำพร้อมตัวอย่างเมื่ออธิบายแนวคิด
ฉันได้อ่านบทความนี้เกี่ยวกับหัวข้อ แต่ฉันไม่เข้าใจจริงๆ โปรดให้คำแนะนำพร้อมตัวอย่างเมื่ออธิบายแนวคิด
คำตอบ:
Java ให้ทั้งสองประเภทที่แตกต่างกัน / ชั้นเรียนของวัตถุอ้างอิง : แข็งแกร่งและอ่อนแอ วัตถุอ้างอิงที่อ่อนแอสามารถแบ่งออกเป็นอ่อนและphantomเพิ่มเติม
ไปกันทีละจุด
วัตถุอ้างอิงที่แข็งแกร่ง
StringBuilder builder = new StringBuilder();
นี่เป็นชนิด / คลาสเริ่มต้นของออบเจกต์อ้างอิงหากไม่ได้ระบุแตกต่างกัน: builder
เป็นออบเจกต์อ้างอิงที่คาดเดายาก การอ้างอิงชนิดนี้ทำให้ออบเจ็กต์ที่อ้างอิงไม่มีสิทธิ์ใช้ GC นั่นคือเมื่อใดก็ตามที่วัตถุถูกอ้างอิงโดยสายโซ่ของวัตถุอ้างอิงที่แข็งแกร่งจะไม่สามารถรวบรวมขยะได้
วัตถุอ้างอิงที่อ่อนแอ
WeakReference<StringBuilder> weakBuilder = new WeakReference<StringBuilder>(builder);
Weak Reference Object ไม่ใช่ประเภท / คลาสเริ่มต้นของ Reference Object และควรใช้พวกมันควรถูกระบุอย่างชัดเจนเช่นในตัวอย่างด้านบน การอ้างอิงชนิดนี้ทำให้ออบเจ็กต์การอ้างอิงมีสิทธิ์ได้รับ GC นั่นคือในกรณีที่การอ้างอิงเพียงอย่างเดียวที่สามารถเข้าถึงได้สำหรับStringBuilder
วัตถุในหน่วยความจำคือจริงๆแล้วการอ้างอิงที่อ่อนแอจากนั้น GC อนุญาตให้ขยะเก็บรวบรวมStringBuilder
วัตถุ เมื่อวัตถุในหน่วยความจำสามารถเข้าถึงได้โดย Weak Reference Objects วัตถุนั้นจะมีสิทธิ์โดยอัตโนมัติสำหรับ GC
ระดับความอ่อนแอ
สองระดับที่แตกต่างกันของความอ่อนแอสามารถเกณฑ์: นุ่มและผี
นุ่มวัตถุอ้างอิงนั้นเป็นวัตถุอ้างอิงอ่อนแอที่ยังคงอยู่ในความทรงจำอีกเล็กน้อย: ปกติก็ต่อต้านวงจร GC จนกว่าหน่วยความจำไม่สามารถใช้ได้และมีความเสี่ยงของOutOfMemoryError
(ในกรณีที่จะสามารถลบออก)
ในทางตรงกันข้ามPhantom Reference Object มีประโยชน์เฉพาะที่จะรู้ว่าเมื่อวัตถุถูกลบออกจากหน่วยความจำอย่างมีประสิทธิภาพ: โดยปกติแล้วพวกเขาจะใช้เพื่อแก้ไขพฤติกรรมแปลกประหลาดสุดท้าย () การฟื้นฟู / การฟื้นคืนชีพเนื่องจากพวกเขาไม่ได้คืนวัตถุเอง ช่วยในการติดตามสถานะหน่วยความจำเท่านั้น
ออบเจ็กต์อ้างอิงที่อ่อนแอนั้นเหมาะสมอย่างยิ่งที่จะนำโมดูลแคช ในความเป็นจริงการเรียงลำดับของการขับไล่อัตโนมัติสามารถทำได้โดยการอนุญาตให้ GC ทำความสะอาดพื้นที่หน่วยความจำเมื่อใดก็ตามที่วัตถุ / ค่าไม่สามารถเข้าถึงได้โดยสายอ้างอิงที่แข็งแกร่ง ตัวอย่างคือWeakHashMap ที่เก็บคีย์อ่อน
ข้อมูลอ้างอิงที่อ่อนแอ:
การอ้างอิงที่อ่อนแอง่าย ๆ คือการอ้างอิงที่ไม่แข็งแรงพอที่จะบังคับให้วัตถุยังคงอยู่ในหน่วยความจำ การอ้างอิงที่อ่อนแอช่วยให้คุณสามารถใช้ความสามารถของตัวเก็บขยะเพื่อกำหนดความสามารถในการเข้าถึงสำหรับคุณดังนั้นคุณไม่จำเป็นต้องทำเอง
อ้างอิงอ่อน:
การอ้างอิงที่นุ่มนวลเป็นเหมือนการอ้างอิงที่อ่อนแอยกเว้นว่ามันมีความกระตือรือร้นน้อยกว่าที่จะโยนวัตถุที่มันอ้างอิง วัตถุที่เข้าถึงได้ง่ายเพียงเล็กน้อย (การอ้างอิงที่แข็งแกร่งที่สุดคือ WeakReferences) จะถูกยกเลิกในรอบการรวบรวมขยะครั้งต่อไป
การอ้างอิงผี:
การอ้างอิงแฝงค่อนข้างแตกต่างจาก SoftReference หรือ WeakReference การยึดเกาะกับวัตถุนั้นผอมบางจนคุณไม่สามารถเรียกคืนวัตถุได้ - เมธอด get () จะคืนค่าว่างเสมอ การใช้งานสำหรับการอ้างอิงเท่านั้นคือการติดตามว่าเมื่อใดที่ได้รับการจัดคิวเข้าสู่ ReferenceQueue ณ จุดนั้นคุณจะรู้ว่าวัตถุที่มันชี้ไปนั้นตายไปแล้ว
ข้อความนี้ถูกดึงมาจาก: https://weblogs.java.net/blog/2006/05/04/understanding-weak-references
ความแตกต่างระหว่างที่เรียบง่ายSoftReference
และWeakReference
ให้บริการโดยนักพัฒนาซอฟต์แวร์ Android
ความแตกต่างระหว่าง a SoftReference
และ a WeakReference
คือเวลาที่การตัดสินใจทำเพื่อให้ชัดเจนและจัดทำเอกสารอ้างอิง:
SoftReference
ควรล้างและ enqueued เป็นปลายที่เป็นไปได้นั่นคือในกรณีที่ VM อยู่ในอันตรายจากการทำงานออกจากหน่วยความจำ
WeakReference
อาจจะล้างและ enqueued เร็วที่สุดเท่าที่เป็นที่รู้จักกันอย่างอ่อนอ้างอิง
คำศัพท์สามคำที่คุณใช้มักเกี่ยวข้องกับการมีสิทธิ์ของวัตถุในการรวบรวมขยะ
Weak Reference :: เป็นข้อมูลอ้างอิงที่ไม่แข็งแรงพอที่จะบังคับให้วัตถุยังคงอยู่ในหน่วยความจำ มันเป็นนักสะสมขยะที่ต้องการรวบรวมวัตถุนั้นสำหรับการรวบรวมขยะ คุณไม่สามารถบังคับให้ GC ไม่เก็บมันได้
Soft Reference :: มันมากหรือน้อยเหมือนการอ้างอิงที่อ่อนแอ แต่คุณสามารถพูดได้ว่ามันเก็บวัตถุได้มากขึ้นกว่าการอ้างอิงที่อ่อนแอจากการรวบรวมขยะ
หากนักสะสมขยะรวบรวมการอ้างอิงที่อ่อนแอในวงจรชีวิตแรกมันจะรวบรวมการอ้างอิงที่อ่อนนุ่มในรอบถัดไปของการรวบรวมขยะ
การอ้างอิงที่แข็งแกร่ง :: ตรงข้ามกับการอ้างอิงสองประเภทข้างต้น พวกเขาชอบเก็บขยะน้อยกว่า (ส่วนใหญ่ไม่เคยถูกรวบรวม)
คุณสามารถดูลิงค์ต่อไปนี้สำหรับข้อมูลเพิ่มเติม:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/ref/Reference.html
นี้บทความจะมีประโยชน์สุดที่จะเข้าใจแข็งแรงนุ่มอ่อนแอและผีอ้างอิง
เพื่อให้คุณสรุป
หากคุณมีการอ้างอิงที่แข็งแกร่งไปยังวัตถุดังนั้น GC จะไม่สามารถรวบรวม / เรียกคืนวัตถุได้
หากคุณมีข้ออ้างอิงที่อ่อนแอไปยังวัตถุ (โดยไม่มีการอ้างอิงที่แข็งแกร่ง) ดังนั้น GC จะเรียกคืนวัตถุในรอบ GC ถัดไป
หากคุณมีการอ้างอิงที่นุ่มนวลไปยังวัตถุ (โดยไม่มีการอ้างอิงที่รัดกุม) วัตถุนั้นจะถูกเรียกคืนโดย GC เฉพาะเมื่อ JVM มีหน่วยความจำไม่เพียงพอ
เราสร้างอ้างอิงผีไปยังวัตถุที่จะติดตามเมื่อวัตถุที่ได้รับการ enqueued ReferenceQueue
เข้าไปใน เมื่อคุณรู้ว่าคุณสามารถทำการสรุปแบบละเอียดได้ (สิ่งนี้จะช่วยให้คุณไม่ต้องฟื้นวัตถุโดยไม่ตั้งใจเนื่องจากการอ้างอิงจาก phantom ไม่ได้ให้การอ้างอิงแก่คุณ) ผมขอแนะนำให้คุณอ่านนี้บทความที่จะได้รับรายละเอียดในเชิงลึกเกี่ยวกับเรื่องนี้
ดังนั้นคุณสามารถพูดได้ว่าการอ้างอิงที่แข็งแกร่งมีพลังอำนาจสูงสุด (ไม่สามารถรวบรวมได้โดย GC)
ซอฟท์อ้างอิงมีประสิทธิภาพมากกว่าการอ้างอิงที่อ่อนแอ (เพราะพวกเขาสามารถหลบหนีวงจร GC จนกระทั่ง JVM หมดหน่วยความจำ)
การอ้างอิงที่อ่อนแอนั้นมีประสิทธิภาพน้อยกว่าการอ้างอิงแบบนุ่มนวล (เนื่องจากไม่สามารถหลีกเลี่ยงวงจร GC ใด ๆ ได้และจะถูกเรียกคืนหากวัตถุนั้นไม่มีการอ้างอิงที่แข็งแกร่งอื่น ๆ )
ร้านอาหารคล้ายคลึง
ตอนนี้ถ้าคุณเป็นลูกค้าที่แข็งแกร่ง (คล้ายกับการอ้างอิงที่แข็งแกร่ง) ถึงแม้ว่าลูกค้าใหม่เข้ามาในร้านอาหารหรือสิ่งที่เคยมีความสุขคุณจะไม่ออกจากโต๊ะ (พื้นที่หน่วยความจำบนกอง) พนักงานเสิร์ฟไม่มีสิทธิ์บอกคุณ (หรือแม้แต่ขอให้คุณ) ออกจากร้านอาหาร
หากคุณเป็นลูกค้าที่อ่อนนุ่ม (คล้ายกับการอ้างอิงที่อ่อนนุ่ม) ดังนั้นหากมีลูกค้าใหม่เข้ามาในร้านอาหารพนักงานเสิร์ฟจะไม่ขอให้คุณออกจากโต๊ะเว้นแต่จะไม่มีโต๊ะว่างเหลืออยู่เพื่อรองรับลูกค้าใหม่ (กล่าวอีกนัยหนึ่งพนักงานเสิร์ฟจะขอให้คุณออกจากโต๊ะเฉพาะเมื่อมีลูกค้าใหม่เข้ามาและไม่มีโต๊ะเหลือสำหรับลูกค้าใหม่นี้)
หากคุณเป็นลูกค้าที่อ่อนแอ (คล้ายกับการอ้างอิงที่อ่อนแอ) พนักงานเสิร์ฟตามความประสงค์ของเขาสามารถ (ณ เวลาใดก็ได้) ขอให้คุณออกจากร้านอาหาร: P
4 องศาอ้างอิง - Strong, Weak, Soft, Phantom
Strong - เป็นการอ้างอิงชนิดหนึ่งซึ่งทำให้ออบเจ็กต์ที่อ้างอิงไม่มีสิทธิ์ใช้ GC เรียนสร้าง เช่น - StringBuilder
Weak - เป็นข้อมูลอ้างอิงที่มีสิทธิ์ได้รับ GC
อ่อนนุ่ม - เป็นการอ้างอิงชนิดหนึ่งซึ่งวัตถุมีสิทธิ์ใช้ GC จนกว่าหน่วยความจำจะพร้อมใช้งาน ดีที่สุดสำหรับแคชรูปภาพ มันจะเก็บไว้จนกว่าหน่วยความจำจะพร้อมใช้งาน
Phantom - เป็นการอ้างอิงชนิดหนึ่งซึ่งวัตถุมีสิทธิ์โดยตรงสำหรับ GC ใช้เพื่อทราบเมื่อวัตถุถูกลบออกจากหน่วยความจำ
การใช้งาน:
ช่วยให้คุณระบุเมื่อวัตถุถูกลบออกจากหน่วยความจำอย่างแน่นอน
เมื่อ
finalize()
เมธอดโอเวอร์โหลดดังนั้น GC อาจไม่เกิดขึ้นตามเวลาที่เหมาะสมสำหรับออบเจ็กต์ที่มีสิทธิ์ GC ของสองคลาส ดังนั้นการอ้างอิงแบบ phantom ทำให้พวกเขามีสิทธิ์ได้รับ GC ก่อนหน้าfinalize()
นี้คือเหตุผลที่คุณสามารถรับOutOfMemoryErrorsได้แม้ว่าฮีปส่วนใหญ่จะเป็นขยะ
การอ้างอิงที่อ่อนแอเหมาะอย่างยิ่งสำหรับการนำโมดูลแคชไปใช้
นี่คือการอ้างอิงวัตถุปกติของคุณซึ่งเราใช้รหัสทุกวัน:
Employee emp = new Employee();
ตัวแปร“ EMP” ถือการอ้างอิงที่รัดกุมกับวัตถุของพนักงานและวัตถุที่สามารถเข้าถึงได้ผ่านห่วงโซ่การอ้างอิงที่แข็งแกร่งใด ๆ จะไม่มีสิทธิ์ได้รับการเก็บขยะ โดยปกตินี่คือสิ่งที่คุณต้องการ แต่ไม่เสมอไป ตอนนี้สมมติว่าเรากำลังดึงพนักงานจำนวนมากจากฐานข้อมูลในคอลเล็กชันหรือแผนที่และเราจำเป็นต้องทำการประมวลผลจำนวนมากเป็นประจำดังนั้นเพื่อให้ประสิทธิภาพเราจะเก็บไว้ในแคช
เท่าที่เป็นสิ่งที่ดี แต่ตอนนี้เราต้องการข้อมูลที่แตกต่างกันและเราไม่ต้องการวัตถุพนักงานเหล่านั้นและสิ่งเหล่านี้ไม่ได้อ้างอิงจากที่ใดก็ได้ยกเว้นแคช ข้อใดทำให้หน่วยความจำรั่วเพราะวัตถุเหล่านี้ไม่ได้ใช้งาน แต่ยังไม่มีสิทธิ์สำหรับการรวบรวมขยะและเราไม่สามารถลบวัตถุเหล่านั้นออกจากแคชได้เพราะเราไม่มีการอ้างอิงถึงพวกเขา ดังนั้นที่นี่เราต้องล้างแคชทั้งหมดด้วยตนเองซึ่งน่าเบื่อหรือเราสามารถใช้การอ้างอิงประเภทอื่นเช่นการอ้างอิงที่อ่อนแอ
การอ้างอิงแบบอ่อนจะไม่ตรึงวัตถุไว้ในหน่วยความจำและจะเป็น GC'd ในวัฏจักร GC ถัดไปหากไม่ได้อ้างอิงจากการอ้างอิงอื่น เราสามารถใช้คลาส WeakReference ซึ่งจัดทำโดย Java เพื่อสร้างแคชด้านบนซึ่งจะไม่เก็บวัตถุที่ไม่ได้อ้างอิงจากที่อื่น
WeakReference<Cache> cache = new WeakReference<Cache>(data);
ในการเข้าถึงข้อมูลคุณต้องโทรไปที่ cache.get () การเรียกเพื่อรับนี้อาจส่งคืน null หากการอ้างอิงที่อ่อนแอคือการรวบรวมขยะ: คุณต้องตรวจสอบค่าที่ส่งคืนเพื่อหลีกเลี่ยง NPE Java มีคอลเลกชันที่ใช้การอ้างอิงที่อ่อนแอเช่นคลาส WeakHashMap จะเก็บคีย์ (ไม่ใช่ค่า) เป็นการอ้างอิงที่อ่อนแอ หากคีย์เป็น GC'd ค่าจะถูกลบออกจากแผนที่โดยอัตโนมัติเช่นกัน
เนื่องจากการอ้างอิงที่อ่อนแอนั้นเป็นวัตถุเราก็จำเป็นต้องมีวิธีในการทำความสะอาดมันด้วย (มันไม่มีประโยชน์อีกต่อไปเมื่อวัตถุที่พวกเขาอ้างถึงนั้นเป็น GC'd) หากคุณส่ง ReferenceQueue ไปยังตัวสร้างสำหรับการอ้างอิงแบบอ่อนตัวรวบรวมขยะจะผนวกการอ้างอิงแบบอ่อนแอนั้นไปยัง ReferenceQueue ก่อนที่จะทำการสรุปหรือ GC'd คุณสามารถประมวลผลคิวนี้เป็นระยะและจัดการกับการอ้างอิงที่ตายแล้ว
SoftReference เหมือนกับ WeakReference แต่มีโอกาสน้อยที่จะถูกรวบรวมขยะ ซอฟต์อ้างอิงจะถูกล้างตามดุลยพินิจของนักสะสมขยะในการตอบสนองความต้องการของหน่วยความจำ เครื่องเสมือนรับประกันว่าการอ้างอิงแบบอ่อนทั้งหมดไปยังออบเจ็กต์ที่เข้าถึงได้อย่างนุ่มนวลจะถูกล้างออกก่อนที่จะส่ง OutOfMemoryError
การอ้างอิงแบบผีคือจุดอ่อนที่สุดของประเภทการอ้างอิงทั้งหมดการเรียกใช้บนการอ้างอิงจะส่งคืนค่าว่างเสมอ วัตถุถูกอ้างอิงแบบ phantomly หลังจากที่ได้รับการสรุป แต่ก่อนที่หน่วยความจำที่จัดสรรไว้จะถูกเรียกคืนซึ่งต่างจากการอ้างอิงแบบอ่อนซึ่งจะถูกจัดคิวไว้ก่อนที่จะทำการสรุปหรือการอ้างอิงแบบผีจะใช้น้อยมาก
แล้วมันมีประโยชน์อย่างไร? เมื่อคุณสร้างการอ้างอิงแบบแฝงคุณต้องผ่านใน ReferenceQueue เสมอ สิ่งนี้บ่งชี้ว่าคุณสามารถใช้การอ้างอิงแฝงเพื่อดูว่าวัตถุของคุณเป็น GC'd หรือไม่
เฮ้ดังนั้นถ้าการอ้างอิงที่ไม่ดีถูกจัดคิวเมื่อพวกเขาถือว่าเสร็จสิ้นแล้ว แต่ยังไม่ถึง GC'd เราสามารถสร้างการอ้างอิงที่แข็งแกร่งใหม่ไปยังวัตถุในบล็อก finalizer และป้องกันไม่ให้วัตถุถูก GC'd ใช่คุณทำได้ แต่คุณอาจไม่ควรทำเช่นนี้ ในการตรวจสอบกรณีนี้วงจร GC จะเกิดขึ้นอย่างน้อยสองครั้งสำหรับแต่ละวัตถุยกเว้นว่าวัตถุนั้นสามารถเข้าถึงได้โดยการอ้างอิงแบบ phantom เท่านั้น นี่คือเหตุผลที่คุณสามารถหมดกองแม้หน่วยความจำของคุณมีขยะมากมาย การอ้างอิงแบบผีสามารถป้องกันสิ่งนี้ได้
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับบทความของฉันประเภทของการอ้างอิงในชวา (แรง, ซอฟท์, อ่อนแอ, ผี)