"สวัสดี! ฉันตัดสินใจที่จะให้บทเรียนเล็ก ๆ น้อย ๆ เกี่ยวกับการเก็บขยะแก่คุณอีกครั้ง"
ดังที่คุณทราบแล้วว่าเครื่อง Java จะตรวจสอบเมื่อวัตถุไม่จำเป็นและลบออก
“ใช่ คุณกับฤๅษีบอกฉันก่อนหน้านี้แล้ว ฉันจำรายละเอียดไม่ได้”
“โอเค งั้นเรามาทบทวนกันอีกครั้ง”
"ทันทีที่อ็อบเจกต์ถูกสร้างขึ้น 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จะถูกทำลาย"
"นั่นคือทั้งหมดที่สำหรับตอนนี้."
"ขอบคุณสำหรับเรื่องราวที่น่าสนใจ เอลลี่ มันน่าสนใจมากจริงๆ"
GO TO FULL VERSION