บทช่วยสอนนี้คือการทำความเข้าใจคอลเล็กชั่นขยะ Java ขั้นพื้นฐานและวิธีการทำงาน นี่เป็นส่วนที่สองของชุดการสอนคอลเล็กชั่นขยะ ฉันหวังว่าคุณจะได้อ่านส่วนแรก: " การแนะนำสั้น ๆ เกี่ยวกับกลไกการเก็บรวบรวมขยะ Java "
Java Garbage Collection เป็นกระบวนการอัตโนมัติที่ใช้ในการจัดการหน่วยความจำรันไทม์ที่ใช้โดยโปรแกรม ผ่านกระบวนการอัตโนมัตินี้ JVM จะลบค่าใช้จ่ายของโปรแกรมเมอร์เพื่อจัดสรรและทรัพยากรหน่วยความจำฟรีในโปรแกรม
เริ่มต้นคอลเลกชันขยะ Java
ในฐานะกระบวนการอัตโนมัติโปรแกรมเมอร์ไม่จำเป็นต้องเริ่มกระบวนการรวบรวมขยะที่แสดงในรหัส System.gc () และ runtime.gc () ใช้เพื่อขอให้ JVM เริ่มต้นการรวบรวมขยะ
แม้ว่ากลไกการร้องขอนี้จะเปิดโอกาสให้โปรแกรมเมอร์เริ่มกระบวนการ GC แต่การเริ่มต้นเป็นความรับผิดชอบของ JVM JVM สามารถปฏิเสธคำขอนี้ได้ดังนั้นจึงไม่มีการรับประกันว่าการโทรทั้งหมดเหล่านี้จะทำการรวบรวมขยะ ตัวเลือกของเวลาเริ่มต้นจะถูกกำหนดโดย JVM และขึ้นอยู่กับว่าพื้นที่ Eden มีอยู่ในหน่วยความจำฮีปหรือไม่ JVM ออกจากตัวเลือกนี้ไปสู่การใช้งานข้อกำหนด Java และอัลกอริทึมเฉพาะที่ใช้โดยการใช้งานที่แตกต่างกันนั้นแตกต่างกัน
ไม่จำเป็นต้องพูดเรารู้ว่ากระบวนการเก็บขยะไม่สามารถบังคับใช้ได้ ฉันเพิ่งพบฉากที่ Calling System.gc () สมเหตุสมผล ผ่านบทความนี้มาเรียนรู้เกี่ยวกับสถานการณ์สุดขั้วที่ เหมาะสำหรับการโทร System.gc ()
กระบวนการรวบรวมขยะ Java
Garbage Collection เป็นกระบวนการในการเรียกคืนพื้นที่หน่วยความจำที่ไร้ประโยชน์และทำให้สามารถใช้งานได้ในอนาคต
พื้นที่อีเด็น: เมื่อมีการสร้างอินสแตนซ์มันจะถูกเก็บไว้ในพื้นที่อีเด็นของหน่วยความจำกองรุ่นเยาว์
หมายเหตุ: หากคุณไม่เข้าใจคำเหล่านี้ฉันขอแนะนำให้คุณอ่านบทนำเกี่ยวกับการรวบรวมขยะซึ่งให้คำแนะนำรายละเอียดเกี่ยวกับโมเดลหน่วยความจำสถาปัตยกรรม JVM และข้อกำหนดเหล่านี้
โซนผู้รอดชีวิต (S0 และ S1): เป็นส่วนหนึ่งของวงจร GC รุ่นใหม่ (MinorGC) วัตถุที่รอดชีวิต (ยังคงอ้างอิง) ถูกย้ายจากโซน Eden ไปยัง S0 ของโซนผู้รอดชีวิต ในทำนองเดียวกันนักสะสมขยะจะสแกน S0 และย้ายอินสแตนซ์ที่รอดชีวิตไปยัง S1
(หมายเหตุของนักแปล: คนที่รอดชีวิตใน Eden และ S0 ย้ายไป S1 หรือไม่ทำไมพวกเขาถึงย้ายไป S0 ก่อนจากนั้นจาก S0 ถึง S1?)
ตัวอย่างของความตาย (ไม่ได้อ้างอิง) ถูกทำเครื่องหมายว่าเป็นคอลเลกชันขยะ ขึ้นอยู่กับตัวเก็บขยะ (มีนักสะสมขยะที่ใช้กันทั่วไปสี่คนซึ่งจะอธิบายไว้ในบทช่วยสอนถัดไป) ไม่ว่าจะเป็นอินสแตนซ์ที่ติดแท็กจะถูกลบออกจากหน่วยความจำอย่างต่อเนื่องหรือกระบวนการรีไซเคิลเสร็จสมบูรณ์ในกระบวนการแยกต่างหาก
รุ่นเก่า: รุ่นเก่าเป็นพื้นที่ตรรกะที่สองในหน่วยความจำกอง เมื่อนักสะสมขยะดำเนินการวงจร Minorgc อินสแตนซ์ที่รอดชีวิตในพื้นที่ S1Survivor จะได้รับการเลื่อนตำแหน่งให้เป็นวัยชราในขณะที่วัตถุที่ไม่ได้อ้างอิงจะถูกทำเครื่องหมายว่าเป็นรีไซเคิล
Old GC (MajorGC): เมื่อเทียบกับกระบวนการรวบรวมขยะ Java GC Old เป็นขั้นตอนสุดท้ายของวัฏจักรชีวิตอินสแตนซ์ MAGINGC สแกนกระบวนการรีไซเคิลขยะของผู้สูงอายุ หากอินสแตนซ์ไม่ได้อ้างอิงอีกต่อไปพวกเขาจะถูกทำเครื่องหมายว่าเป็นรีไซเคิลมิฉะนั้นพวกเขาจะยังคงอยู่ในวัยชรา
หน่วยความจำชาร์ด: เมื่ออินสแตนซ์ถูกลบออกจากหน่วยความจำฮีปตำแหน่งของมันจะว่างเปล่าและสามารถใช้สำหรับการจัดสรรอินสแตนซ์ในอนาคต พื้นที่ว่างเหล่านี้จะแยกส่วนพื้นที่หน่วยความจำทั้งหมด สำหรับการจัดสรรอินสแตนซ์อย่างรวดเร็วจำเป็นต้องมีการจัดเรียงข้อมูล ขึ้นอยู่กับตัวเลือกที่แตกต่างกันของตัวเก็บขยะพื้นที่หน่วยความจำรีไซเคิลจะถูกจัดเรียงอย่างต่อเนื่องหรือเสร็จสมบูรณ์ในกระบวนการ GC แยกต่างหาก
จุดสิ้นสุดของอินสแตนซ์ในการรวบรวมขยะ
ก่อนที่จะปลดปล่อยอินสแตนซ์และการเรียกคืนพื้นที่หน่วยความจำนักสะสม Java Garbage เรียกวิธีการสรุปของอินสแตนซ์ () เพื่อให้อินสแตนซ์มีโอกาสที่จะเพิ่มทรัพยากรที่เก็บไว้ แม้ว่าจะรับประกันได้ว่าจะเรียกว่า finalize () ก่อนที่จะเรียกคืนพื้นที่หน่วยความจำ แต่ก็ไม่มีคำสั่งและเวลาที่ระบุ ลำดับระหว่างหลาย ๆ กรณีไม่สามารถคาดการณ์ได้และอาจเกิดขึ้นพร้อมกัน โปรแกรมไม่ควรปรับลำดับระหว่างอินสแตนซ์และรีไซเคิลทรัพยากรโดยใช้วิธีการสรุป ()
ข้อยกเว้นใด ๆ ที่ไม่ได้ถูกจับในกระบวนการสุดท้ายจะถูกละเว้นโดยอัตโนมัติและกระบวนการสุดท้ายของอินสแตนซ์จะถูกยกเลิก
ข้อกำหนด JVM ไม่ได้หารือเกี่ยวกับกลไกการรวบรวมขยะสำหรับการอ้างอิงที่อ่อนแอและไม่มีข้อกำหนดที่ชัดเจน การใช้งานเฉพาะจะถูกกำหนดโดยฝ่ายดำเนินการ
คอลเล็กชั่นขยะทำโดยด้ายดุล
วัตถุจะตรงตามเงื่อนไขสำหรับการรวบรวมขยะเมื่อใด
อินสแตนซ์ทั้งหมดไม่มีการเข้าถึงเธรดที่ใช้งานอยู่
อินสแตนซ์อ้างอิงแบบวงกลมที่ไม่สามารถเข้าถึงได้โดยอินสแตนซ์อื่น ๆ
มีประเภทอ้างอิงที่แตกต่างกันใน Java การพิจารณาว่าอินสแตนซ์เป็นไปตามเงื่อนไขการรวบรวมขยะทั้งหมดขึ้นอยู่กับประเภทการอ้างอิงหรือไม่
| ประเภทอ้างอิง | คอลเลกชันขยะ |
|---|---|
| การอ้างอิงที่แข็งแกร่ง | ไม่สอดคล้องกับการรวบรวมขยะ |
| ข้อมูลอ้างอิงที่อ่อนนุ่ม | อาจมีการเก็บรวบรวมขยะ แต่จะเป็นทางเลือกสุดท้าย |
| ข้อมูลอ้างอิงที่อ่อนแอ | ปฏิบัติตามคอลเลกชันขยะ |
| การอ้างอิง Phantom | ปฏิบัติตามคอลเลกชันขยะ |
ในฐานะที่เป็นเทคนิคการปรับให้เหมาะสมในระหว่างกระบวนการรวบรวมคอมไพเลอร์ Java สามารถเลือกที่จะกำหนดค่า NULL ให้กับอินสแตนซ์ซึ่งจะทำเครื่องหมายอินสแตนซ์เป็นรีไซเคิลได้
สัตว์ชั้น {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {สัตว์สิงโต = สัตว์ใหม่ (); System.out.println ("หลักเสร็จสมบูรณ์"); } การป้องกันโมฆะจบลง () {system.out.println ("พักผ่อนอย่างสงบ!"); -ในคลาสข้างต้นวัตถุสิงโตไม่เคยถูกใช้หลังจากอินสแตนซ์เส้น ดังนั้นในการวัดการเพิ่มประสิทธิภาพคอมไพเลอร์ Java สามารถกำหนด Lion = Null ได้โดยตรงหลังจากอินสแตนซ์แถว ดังนั้นฟังก์ชั่นสุดท้ายสามารถพิมพ์ 'RestInpeace!' แม้กระทั่งก่อนเอาต์พุต SOP เราไม่สามารถพิสูจน์ได้ว่าสิ่งนี้จะเกิดขึ้นเพราะมันขึ้นอยู่กับวิธีการใช้งาน JVM และหน่วยความจำที่ใช้โดยรันไทม์ อย่างไรก็ตามเราสามารถเรียนรู้อีกหนึ่ง: หากคอมไพเลอร์เห็นว่าอินสแตนซ์จะไม่ถูกอ้างอิงในอนาคตมันสามารถเลือกและว่างพื้นที่อินสแตนซ์ได้เร็ว
มีตัวอย่างที่ดีกว่าเมื่อวัตถุปฏิบัติตามคอลเลกชันขยะ คุณลักษณะทั้งหมดของอินสแตนซ์สามารถเก็บไว้ในการลงทะเบียนซึ่งจะสามารถเข้าถึงและอ่านได้ โดยไม่มีข้อยกเว้นค่าเหล่านี้จะถูกเขียนกลับไปที่อินสแตนซ์ แม้ว่าค่าเหล่านี้สามารถใช้ในอนาคตอินสแตนซ์นี้ยังคงสามารถทำเครื่องหมายได้ว่าสอดคล้องกับการรวบรวมขยะ นี่เป็นตัวอย่างที่คลาสสิกมากใช่มั้ย
นี่เป็นตัวอย่างที่ง่ายมากที่สอดคล้องกับการรวบรวมขยะเมื่อได้รับมอบหมายให้เป็นโมฆะ แน่นอนว่าสถานการณ์ที่ซับซ้อนอาจเป็นเหมือนคะแนนข้างต้น นี่คือตัวเลือกที่ทำโดยผู้ดำเนินการ JVM จุดประสงค์คือการปล่อยให้รอยเท้าหน่วยความจำที่เล็กที่สุดเท่าที่จะเป็นไปได้เพิ่มความเร็วในการตอบสนองและปรับปรุงปริมาณงาน เพื่อให้บรรลุเป้าหมายนี้ผู้ใช้ JVM สามารถเลือกโซลูชันหรืออัลกอริทึมที่ดีกว่าเพื่อเรียกคืนพื้นที่หน่วยความจำในระหว่างกระบวนการรวบรวมขยะ
เมื่อมีการเรียกวิธีการสรุป () JVM จะปล่อยการซิงโครไนซ์ทั้งหมดในเธรด
โปรแกรมตัวอย่าง GCSCOPE
คลาส GCSCOPE {GCSCOPE T; Static int i = 1; โมฆะคงที่สาธารณะ (สตริง args []) {gcScope t1 = ใหม่ gcscope (); gcscope t2 = ใหม่ gcscope (); gcscope t3 = gcscope ใหม่ มีสิทธิ์สำหรับ gct3.t = t1; // ไม่มีวัตถุที่มีสิทธิ์ได้รับ gct1 = null; // ไม่มีวัตถุที่มีสิทธิ์สำหรับ GC (t3. ยังมีการอ้างอิงถึง t1) t2 = null; // ไม่มีวัตถุที่มีสิทธิ์สำหรับ GC (t3.tt ยังมีการอ้างอิง t2) t3 = null ซึ่งกันและกันใน A // แฟชั่นที่โค้งมนสร้างเกาะวัตถุโดยไม่มีการอ้างอิงภายนอก //)} void protected finalize () {system.out.println ("ขยะที่เก็บรวบรวมจากวัตถุ"+i); i ++;} คลาส gcscope {gcscope t; gcscope (); gcscope t2 = new gcscope (); gcscope t3 = new gcscope (); // ไม่มีวัตถุที่สอดคล้องกับ gct1.t = t2; // ไม่มีวัตถุที่สอดคล้องกับ gct2.t = t3; // ไม่มีวัตถุสอดคล้องกับ gct3.t = t1; t1) t2 = null; // ไม่มีวัตถุที่สอดคล้องกับ GC (T3.TT ยังคงมีการอ้างอิงถึง T2) t3 = null; // วัตถุทั้งสามนั้นสอดคล้องกับ GC (ไม่มีของพวกเขาที่มีการอ้างอิง // เฉพาะตัวแปรของแต่ละวัตถุ จากวัตถุ "+i); i ++;}โปรแกรมตัวอย่าง GC OutofMemoryError
GC ไม่รับประกันความปลอดภัยของปัญหาการไหลล้นหน่วยความจำและการเขียนโค้ดประมาทจะทำให้ OutofMemoryError
นำเข้า java.util.linkedList; นำเข้า java.util.list; คลาสสาธารณะ GC {โมฆะคงที่สาธารณะหลัก (สตริง [] หลัก) {รายการ l = ใหม่ linkedList (); // ป้อนลูปอนันต์ซึ่งจะเพิ่มสตริงลงในรายการ: l ในแต่ละ // iteration.do {l.addเอาท์พุท:
ข้อยกเว้นในเธรด "Main Main" java.lang.outofMemoryError: พื้นที่ java heap ที่ java.util.linkedlist.linklast (linkedlist.java:142) ที่ java.util.linkedlist.add (LinkedList.java:338) com.javapapers.java.gcscope.main (gcscope.java:12)
สรุป
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้เกี่ยวกับการพูดคุยสั้น ๆ เกี่ยวกับกระบวนการดำเนินการของการรวบรวมขยะ Java ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!