เรียกคืนการรวบรวมขยะใน Java
การรวบรวมขยะคือกระบวนการเรียกคืนหน่วยความจำรันไทม์แบบเต็มโดยการทำลายวัตถุที่ไม่ได้ใช้
บางครั้งโปรแกรมเมอร์อาจลืมที่จะทำลายวัตถุที่ไร้ประโยชน์ และหน่วยความจำที่จัดสรรให้นั้นจะไม่ว่าง มีการใช้หน่วยความจำระบบมากขึ้นเรื่อยๆ และในที่สุดก็ไม่มีการจัดสรรอีกต่อไป แอปพลิเคชันดังกล่าวประสบปัญหา "หน่วยความจำรั่ว"
หลังจากถึงจุดหนึ่ง หน่วยความจำไม่เพียงพอที่จะสร้างวัตถุใหม่อีกต่อไป และโปรแกรมจะหยุดทำงานอย่างผิดปกติเนื่องจากOutOfMemoryError
![](https://cdn.codegym.cc/images/article/3000851c-d7b0-48c1-a1b0-42fc199942d5/800.jpeg)
การรวบรวมขยะใน Java เป็นกระบวนการที่โปรแกรม Java จัดการหน่วยความจำโดยอัตโนมัติ โปรแกรม Java ถูกคอมไพล์เป็น bytecode ที่ทำงานบน Java Virtual Machine (JVM)
เมื่อโปรแกรม Java ทำงานบน JVM อ็อบเจ็กต์จะถูกสร้างขึ้นบนฮีป ซึ่งเป็นส่วนของหน่วยความจำที่จัดสรรให้
ในขณะที่แอปพลิเคชัน Java กำลังทำงาน วัตถุใหม่จะถูกสร้างขึ้นในนั้น ในที่สุดวัตถุบางอย่างก็ไม่จำเป็นอีกต่อไป เราสามารถพูดได้ว่า ณ เวลาใดเวลาหนึ่ง หน่วยความจำฮีปประกอบด้วยวัตถุสองประเภท
- สด - วัตถุเหล่านี้ถูกใช้ มันถูกอ้างอิงจากที่อื่น
- ตาย - วัตถุเหล่านี้ไม่ได้ใช้ที่อื่นไม่มีการอ้างอิงถึงพวกเขา
ตัวรวบรวมขยะจะค้นหาวัตถุที่ไม่ได้ใช้เหล่านี้และลบออกเพื่อเพิ่มหน่วยความจำ
การรวบรวมขยะใน Java เป็นกระบวนการอัตโนมัติ โปรแกรมเมอร์ไม่จำเป็นต้องทำเครื่องหมายวัตถุที่จะลบอย่างชัดเจน
JVM แต่ละรายการสามารถใช้การรวบรวมขยะในเวอร์ชันของตนเองได้ อย่างไรก็ตาม ตัวรวบรวมต้องเป็นไปตามข้อกำหนดมาตรฐาน JVM สำหรับจัดการกับออบเจกต์ที่มีอยู่ในหน่วยความจำฮีปเพื่อทำเครื่องหมายหรือระบุออบเจ็กต์ที่ไม่สามารถเข้าถึงได้และทำลายผ่านการบีบอัด
ความสามารถในการเข้าถึงวัตถุ
เพื่อให้รู้ว่าวัตถุมีชีวิต การมีลิงก์ไม่เพียงพอ นี่เป็นเพราะวัตถุที่ตายแล้วบางอย่างสามารถอ้างถึงวัตถุที่ตายแล้วอื่นๆ นั่นเป็นเหตุผลว่าเหตุใดจึงมีความจำเป็นที่การอ้างอิงถึงวัตถุทั้งหมด ควรมีอย่างน้อยหนึ่งรายการจากวัตถุ "สด"
![ความสามารถในการเข้าถึงวัตถุ](https://cdn.codegym.cc/images/article/eb12b7bc-7401-440e-a551-9b4461ba3b5d/800.jpeg)
คนเก็บขยะทำงานโดยใช้แนวคิดของ GC Roots ( รากของการเก็บขยะ ) เพื่อแยกความแตกต่างระหว่างวัตถุที่มีชีวิตและวัตถุที่ตายแล้ว มีวัตถุมีชีวิต 100% และมีลิงก์ที่ทำให้วัตถุอื่นเคลื่อนไหวเป็นต้น
ตัวอย่างของรากดังกล่าว:
- คลาสที่โหลดโดยตัวโหลดคลาสของระบบ
- สตรีมสด
- พารามิเตอร์ของวิธีการดำเนินการในปัจจุบันและตัวแปรท้องถิ่น
- อ็อบเจ็กต์ที่ใช้เป็นมอนิเตอร์สำหรับการซิงโครไนซ์
- วัตถุที่เก็บไว้จากการรวบรวมขยะเพื่อวัตถุประสงค์บางอย่าง
- ตัวรวบรวมขยะจะอธิบายกราฟทั้งหมดของวัตถุในหน่วยความจำ โดยเริ่มต้นที่รากเหล่านี้และตามด้วยการอ้างอิงถึงวัตถุอื่นๆ
ขั้นตอนการรวบรวมขยะใน Java
การดำเนินการรวบรวมขยะมาตรฐานมีสามขั้นตอน
1. ทำเครื่องหมายวัตถุเป็นสด
ณ จุดนี้ ตัวรวบรวมขยะ (GC) จะต้องระบุวัตถุที่มีชีวิตทั้งหมดในหน่วยความจำโดยการสำรวจกราฟวัตถุ
เมื่อมันเข้าไปที่วัตถุ มันทำเครื่องหมายว่าพร้อมใช้งานและมีชีวิต อ็อบเจ็กต์ทั้งหมดที่ไม่สามารถเข้าถึงได้จากรูท GC ถือเป็นตัวเลือกสำหรับการรวบรวมขยะ
![](https://cdn.codegym.cc/images/article/483e8406-ce8f-458a-8217-c6c2e2c70b2c/800.jpeg)
2. ทำความสะอาดวัตถุที่ตายแล้ว
หลังจากระยะมาร์กอัป พื้นที่หน่วยความจำจะถูกครอบครองโดยออบเจกต์ที่มีชีวิต (เยี่ยมชม) หรือวัตถุที่ตายแล้ว (ไม่ได้เยี่ยมชม) ขั้นตอนการล้างจะปลดปล่อยชิ้นส่วนหน่วยความจำที่มีวัตถุที่ตายแล้วเหล่านี้
![](https://cdn.codegym.cc/images/article/f10e166d-d9bf-462d-9d65-2c81df1b3457/800.jpeg)
3. การจัดเรียงวัตถุที่เหลืออยู่ในหน่วยความจำอย่างกะทัดรัด
ไม่จำเป็นสำหรับวัตถุที่ตายแล้วที่ถูกลบออกไปในเฟสก่อนหน้าที่จะอยู่ติดกัน ดังนั้น คุณจึงเสี่ยงที่จะได้พื้นที่หน่วยความจำที่มีการแยกส่วน (ว่างครึ่งหนึ่ง)
แต่แน่นอนว่าเมื่อจัดเตรียมสิ่งนี้แล้ว มันเป็นไปได้ที่จะกระชับหน่วยความจำในขณะที่ตัวรวบรวมขยะเอาวัตถุที่ตายแล้วออก ส่วนที่เหลือจะอยู่ในบล็อกที่อยู่ติดกันที่จุดเริ่มต้นของกอง
กระบวนการบีบอัดช่วยให้จัดสรรหน่วยความจำตามลำดับสำหรับวัตถุใหม่ได้ง่ายขึ้น
![](https://cdn.codegym.cc/images/article/7008ce12-e886-44e5-8812-8431b4f7c741/800.jpeg)
GO TO FULL VERSION