"สวัสดี! ฉันตัดสินใจที่จะให้บทเรียนเล็ก ๆ น้อย ๆ เกี่ยวกับการเก็บขยะแก่คุณอีกครั้ง"

ดังที่คุณทราบแล้วว่าเครื่อง Java จะตรวจสอบเมื่อวัตถุไม่จำเป็นและลบออก

“ใช่ คุณกับฤๅษีบอกฉันก่อนหน้านี้แล้ว ฉันจำรายละเอียดไม่ได้”

“โอเค งั้นเรามาทบทวนกันอีกครั้ง”

การเก็บขยะ - 1

"ทันทีที่อ็อบเจกต์ถูกสร้างขึ้น JVM จะจัดสรรหน่วยความจำให้กับมัน ความสนใจในอ็อบเจ็กต์จะถูกตรวจสอบโดยใช้ตัวแปรอ้างอิง  อ็อบเจ็กต์สามารถลบออกได้ในระหว่างการรวบรวมขยะ นั่นคือขั้นตอนที่หน่วยความจำถูกปล่อยหากไม่มีตัวแปรที่อ้างอิงถึง วัตถุ. "

"บอกฉันเล็กน้อยเกี่ยวกับคนเก็บขยะ - มันคืออะไรและทำงานอย่างไร"

"ตกลงการรวบรวมขยะเคยเกิดขึ้นในเธรดหลัก ทุก 5 นาทีหรือบ่อยกว่านั้น หากมีหน่วยความจำว่างไม่เพียงพอ เครื่อง Java จะระงับเธรดทั้งหมดและลบอ็อบเจ็กต์ที่ไม่ได้ใช้"

"แต่วิธีการนี้ถูกยกเลิกไปแล้วในขณะนี้ ตัวรวบรวมขยะรุ่นต่อไปทำงานเบื้องหลังและในเธรดที่แยกจากกัน สิ่งนี้เรียกว่าการรวบรวมขยะพร้อมกัน"

"ฉันเข้าใจแล้ว การตัดสินใจว่าจะลบวัตถุหรือไม่ทำเป็นอย่างไรกันแน่"

"การนับจำนวนการอ้างอิงถึงวัตถุนั้นไม่ได้ผลมากนัก อาจมีวัตถุที่อ้างอิงถึงกัน แต่ไม่มีวัตถุอื่นอ้างอิง"

"ดังนั้น Java จึงใช้แนวทางที่แตกต่างกัน  Java แบ่งอ็อบเจกต์ออกเป็นอ็อบเจ็กต์ที่เข้าถึงได้และเข้าถึงไม่ได้  อ็อบเจ็กต์สามารถเข้าถึงได้ (มีชีวิต) หากถูกอ้างอิงโดยอ็อบเจ็กต์ที่เข้าถึงได้ (มีชีวิต) อื่น ความสามารถในการเข้าถึงถูกกำหนดจากเธรด เธรดที่รันจะถือว่าเข้าถึงได้ (มีชีวิต) เสมอ แม้จะไม่มีใครอ้างอิงก็ตาม"

"ตกลง ฉันคิดว่าฉันเข้าใจแล้ว"

"การรวบรวมขยะจริงเกิดขึ้นได้อย่างไร - การลบวัตถุที่ไม่จำเป็น"

"มันง่ายมาก ใน Java หน่วยความจำถูกแบ่งออกเป็นสองส่วนตามแบบแผน และเมื่อถึงเวลาสำหรับการรวบรวมขยะ อ็อบเจ็กต์ที่มีชีวิต (เข้าถึงได้) ทั้งหมดจะถูกคัดลอกไปยังอีกส่วนหนึ่งของหน่วยความจำ และหน่วยความจำเก่าจะถูกรีลีสทั้งหมด"

"นั่นเป็นวิธีการที่น่าสนใจ ไม่จำเป็นต้องนับการอ้างอิง: คัดลอกออบเจกต์ที่เข้าถึงได้ทั้งหมด และอย่างอื่นที่เหลือคือขยะ"

"มันซับซ้อนกว่านั้นเล็กน้อย โปรแกรมเมอร์ Java พบว่าออบเจกต์มักจะแบ่งออกเป็นสองประเภท: อายุยืน (ซึ่งมีอยู่ตลอดเวลาที่โปรแกรมทำงาน) และอายุสั้น (ซึ่งจำเป็นในวิธีการและสำหรับการดำเนินการ «โลคอล » การดำเนินงาน)"

"การแยกวัตถุที่มีอายุยืนยาวออกจากวัตถุที่มีอายุสั้นจะมีประสิทธิภาพมากกว่ามาก ในการทำเช่นนี้ จำเป็นต้องหาวิธีกำหนดอายุยืนของวัตถุ"

"ดังนั้น พวกเขาจึงแบ่งหน่วยความจำทั้งหมดออกเป็น «รุ่น» มีวัตถุรุ่นแรก วัตถุรุ่นที่สอง ฯลฯ ทุกครั้งที่หน่วยความจำถูกล้าง ตัวนับการสร้างจะเพิ่มขึ้น 1 ถ้าวัตถุบางอย่างอยู่ในหลายชั่วอายุคน ถูกบันทึกไว้ว่ามีอายุยืน"

"ทุกวันนี้ ตัวรวบรวมขยะเป็นส่วนที่ซับซ้อนและมีประสิทธิภาพมากของ Java หลายส่วนของมันทำงานแบบฮิวริสติก โดยอิงตามอัลกอริทึมที่คาดเดาได้ ผลก็คือ มัก «ไม่ฟัง» ผู้ใช้"

"ความหมาย?"

"Java มีวัตถุตัวรวบรวมขยะ ( GC ) ที่สามารถเรียกใช้ได้โดยใช้ เมธอด System.gc ()"

"คุณยังสามารถใช้System.runFinalization()เพื่อบังคับการเรียกใช้เมธอดการสิ้นสุดของออบเจกต์ที่จะลบ แต่ความจริงก็คือตามเอกสาร Java สิ่งนี้รับประกันว่าการรวบรวมขยะจะไม่เริ่มขึ้นหรือจบการทำงาน ( ) จะถูกเรียกใช้เมธอด  ตัวรวบรวมขยะ ตัดสินใจว่าจะเรียกเมื่อใดและอะไร "

"โอ้โห! น่ารู้"

"แต่ยังมีมากกว่านั้น อย่างที่คุณทราบ ใน Java อ็อบเจ็กต์บางตัวอ้างอิงถึงอ็อบเจกต์อื่น เครือข่ายการอ้างอิงนี้ใช้เพื่อกำหนดว่าอ็อบเจ็กต์ควรถูกลบหรือไม่"

"และดูสิ Java มีการอ้างอิงพิเศษที่ให้คุณมีอิทธิพลต่อกระบวนการนี้ มีคลาส wrapper พิเศษสำหรับพวกเขา นี่คือ:"

" SoftReference  เป็นการอ้างอิงที่นุ่มนวล"

" WeakReference  คือการอ้างอิงที่อ่อนแอ"

" PhantomReferenceเป็นข้อมูลอ้างอิงแฝง"

"เอ่อ... นี่ทำให้ฉันนึกถึงคลาสภายใน คลาสที่ซ้อนกัน คลาสนิรนามที่ซ้อนกัน และคลาสโลคัล ชื่อต่างกัน แต่ยังไม่ชัดเจนว่ามีไว้เพื่ออะไร"

"พูดว่า Amigo คุณได้กลายเป็นโปรแกรมเมอร์แล้ว ตอนนี้คุณโกรธเพราะชื่อคลาส โดยพูดว่า «ไม่มีข้อมูลเพียงพอ และเป็นไปไม่ได้ด้วยชื่อเดียว (!) ที่จะตัดสินว่าคลาสนี้ทำอะไร อย่างไร และทำไม"."

"ว้าว ฉันไม่ได้สังเกตเลย แต่มันชัดเจนมาก"

"ตกลง พอแล้ว ให้ฉันบอกคุณเกี่ยวกับ SoftReferences"

"การอ้างอิงเหล่านี้ได้รับการออกแบบมาโดยเฉพาะสำหรับการแคช แม้ว่าจะสามารถใช้เพื่อวัตถุประสงค์อื่นได้ ทั้งหมดนี้ขึ้นอยู่กับดุลยพินิจของโปรแกรมเมอร์"

"นี่คือตัวอย่างการอ้างอิงดังกล่าว:"

ตัวอย่าง
// Create a Cat object
Cat cat = new Cat();

// Create a soft reference to a Cat object
SoftReference<Cat> catRef = new SoftReference<Cat>(cat);

// Now only the catRef soft reference points at the object
cat = null;

// Now the ordinary cat variable also references the object
cat = catRef.get();

// Clear the soft reference
catRef.clear();

"หากเพียงการอ้างอิงถึงวัตถุอย่างนุ่มนวล มันก็ยังคงมีชีวิตต่อไป และเรียกว่า 'เข้าถึงได้อย่างนุ่มนวล'"

"แต่!  ตัวรวบรวมขยะสามารถลบวัตถุที่อ้างถึงโดยการอ้างอิงแบบซอฟต์เท่านั้นหากโปรแกรมมีหน่วยความจำไม่เพียงพอ  หากจู่ๆ โปรแกรมมีหน่วยความจำไม่เพียงพอ ก่อนที่จะโยนOutOfMemoryExceptionตัวรวบรวมขยะจะลบวัตถุทั้งหมด อ้างอิงโดย soft references และจะพยายามจัดสรรหน่วยความจำให้กับโปรแกรมอีกครั้ง"

"สมมติว่าโปรแกรมไคลเอ็นต์ร้องขอข้อมูลต่างๆ จากโปรแกรมเซิร์ฟเวอร์บ่อยๆ โปรแกรมเซิร์ฟเวอร์สามารถใช้ SoftReference เพื่อแคชข้อมูลบางส่วนได้ หากวัตถุที่เก็บไว้ไม่ให้ตายโดยการอ้างอิงแบบซอฟต์ใช้พื้นที่ส่วนใหญ่ของหน่วยความจำ จากนั้นตัวเก็บขยะก็จะลบออก ทั้งหมด มันสวย!"

"ใช่ ฉันชอบมันเอง"

"การเพิ่มเติมเล็กน้อย: คลาส SoftReferenceมีสองเมธอด เมธอด get() ส่งคืนวัตถุที่อ้างอิงโดย SoftReference หากวัตถุถูกลบโดยตัวเก็บขยะเมธอด get () จะเริ่มคืนค่า null ในทันที"

"ผู้ใช้ยังสามารถล้างข้อมูล SoftReferenceอย่างชัดเจนได้ด้วยการเรียกใช้เมธอด clear() ในกรณีนี้ ลิงก์ที่อ่อนแอภายใน วัตถุ SoftReferenceจะถูกทำลาย"

"นั่นคือทั้งหมดที่สำหรับตอนนี้."

"ขอบคุณสำหรับเรื่องราวที่น่าสนใจ เอลลี่ มันน่าสนใจมากจริงๆ"