เมื่อพูดถึง Garbage Collection (GC) หลายคนจะเชื่อมโยงกับ Java โดยธรรมชาติ ใน Java โปรแกรมเมอร์ไม่จำเป็นต้องใส่ใจเกี่ยวกับการจัดสรรหน่วยความจำแบบไดนามิกและการรวบรวมขยะทั้งหมดนี้ถูกทิ้งไว้ที่ JVM เพื่อจัดการ
ตามชื่อที่แนะนำคอลเลกชันขยะคือการเพิ่มพื้นที่ว่างโดยขยะ ดังนั้นใน Java วัตถุชนิดใดที่จะถูกพิจารณาว่า "ขยะ"? ดังนั้นเมื่อวัตถุบางอย่างถูกกำหนดให้เป็นขยะควรใช้กลยุทธ์อะไรในการรีไซเคิล (พื้นที่ว่างฟรี) นักสะสมขยะทั่วไปในเครื่องเสมือนเชิงพาณิชย์ปัจจุบันคืออะไร? มาพูดคุยเกี่ยวกับปัญหาเหล่านี้ทีละคน นี่คือโครงร่างไดเรกทอรีของบทความนี้:
จะพิจารณาได้อย่างไรว่าวัตถุเป็น "ขยะ" หรือไม่?
อัลกอริทึมการรวบรวมขยะทั่วไป
1. จะตรวจสอบได้อย่างไรว่าวัตถุเป็น "ขยะ" หรือไม่?
ในส่วนนี้ก่อนอื่นเราเข้าใจคำถามพื้นฐานที่สุด: หากเราพิจารณาว่าวัตถุคือ "ขยะ"? เนื่องจากภารกิจของนักสะสมขยะคือการรีไซเคิลพื้นที่ที่ครอบครองโดยวัตถุขยะเพื่อใช้งานโดยวัตถุใหม่ตัวสะสมขยะจะกำหนดว่าวัตถุเป็น "ขยะ" ได้อย่างไร นั่นคือวิธีการตัดสินว่าวัตถุสามารถรีไซเคิลได้
ใน Java มันเกี่ยวข้องกับวัตถุผ่านการอ้างอิงนั่นคือถ้าคุณต้องการใช้งานวัตถุจะต้องทำผ่านการอ้างอิง จากนั้นก็เห็นได้ชัดว่าวิธีง่ายๆคือการตัดสินว่าวัตถุสามารถรีไซเคิลได้โดยการนับการอ้างอิงหรือไม่ หากไม่มีการสูญเสียทั่วไปหากวัตถุไม่มีการอ้างอิงที่เกี่ยวข้องก็หมายความว่าวัตถุนั้นไม่น่าจะใช้ที่อื่นและจากนั้นวัตถุจะกลายเป็นวัตถุรีไซเคิล วิธีนี้กลายเป็นวิธีการนับอ้างอิง
วิธีนี้มีลักษณะโดยการใช้งานอย่างง่ายและมีประสิทธิภาพสูง แต่ไม่สามารถแก้ปัญหาการอ้างอิงแบบวงกลมได้ดังนั้นวิธีนี้จึงไม่ได้นำมาใช้ใน Java (Python ใช้วิธีการนับอ้างอิง) ดูรหัสต่อไปนี้:
คลาสสาธารณะหลัก {โมฆะคงที่สาธารณะหลัก (สตริง [] args) {myObject object1 = new myObject (); myObject object2 = new myObject (); Object1.Object = Object2; Object2.Object = Object1; Object1 = null; Object2 = null; }} คลาส myObject {วัตถุสาธารณะวัตถุ = null;}สองประโยคสุดท้ายกำหนด Object1 และ Object2 ให้กับ NULL ซึ่งหมายความว่าวัตถุที่ชี้ไปที่ Object1 และ Object2 ไม่สามารถเข้าถึงได้อีกต่อไป แต่เนื่องจากพวกเขาอ้างถึงกันและกันจำนวนการอ้างอิงของพวกเขาไม่ใช่ 0 แล้วตัวเก็บขยะจะไม่รีไซเคิลพวกเขา
เพื่อแก้ปัญหานี้ได้ใช้วิธีการวิเคราะห์ความสามารถในการเข้าถึงใน Java แนวคิดพื้นฐานของวิธีนี้คือการค้นหาผ่านชุดของวัตถุ "GC Roots" เป็นจุดเริ่มต้น หากไม่มีเส้นทางที่สามารถเข้าถึงได้ระหว่าง "ราก GC" และวัตถุวัตถุนั้นจะถูกกล่าวว่าไม่สามารถเข้าถึงได้ อย่างไรก็ตามควรสังเกตว่าวัตถุที่ตัดสินว่าไม่สามารถเข้าถึงได้อาจไม่จำเป็นต้องกลายเป็นวัตถุที่รีไซเคิลได้ วัตถุที่ถูกตัดสินว่าไม่สามารถเข้าถึงได้ต้องผ่านกระบวนการทำเครื่องหมายอย่างน้อยสองกระบวนการเพื่อให้กลายเป็นวัตถุรีไซเคิลได้ หากยังไม่มีความเป็นไปได้ที่จะกลายเป็นวัตถุรีไซเคิลในระหว่างกระบวนการทำเครื่องหมายทั้งสองนี้มันจะกลายเป็นวัตถุรีไซเคิลได้
สำหรับวิธีการวิเคราะห์การเข้าถึงการเข้าถึงฉันยังไม่เข้าใจอย่างชัดเจน หากเพื่อนคนใดมีความชัดเจนมากขึ้นโปรดให้คำแนะนำกับฉัน
มาดูตัวอย่างด้านล่าง:
Object AOBJ = New Object (); Object Bobj = New Object (); Object Cobj = New Object (); aobj = bobj; aobj = cobj; cobj = null; aobj = null;
บรรทัดใดที่อาจทำให้วัตถุรีไซเคิลได้? รหัสในบรรทัดที่ 7 จะทำให้วัตถุกลายเป็นวัตถุรีไซเคิลได้ สำหรับสาเหตุที่ทำให้ผู้อ่านต้องคิดด้วยตัวเอง
ลองมาดูตัวอย่างอื่น:
string str = สตริงใหม่ ("hello"); softreference <string> sr = softreference ใหม่ <string> (สตริงใหม่ ("java")); beakreference <string> wr = new beakreference <string> (สตริงใหม่ ("โลก"));ประโยคใดในสามประโยคใดที่จะทำให้วัตถุสตริงรีไซเคิลได้ ประโยค 2 และ 3 และประโยค 2 จะกำหนดวัตถุสตริงเป็นวัตถุรีไซเคิลเมื่อมีหน่วยความจำไม่เพียงพอและในประโยคที่สามวัตถุสตริงจะถูกกำหนดเป็นวัตถุรีไซเคิลในทุกกรณี
สุดท้ายมาสรุปสถานการณ์ทั่วไปที่วัตถุถูกตัดสินว่าเป็นวัตถุรีไซเคิลที่มักจะพบ:
1) แสดงค่าของการอ้างอิงถึง null หรือชี้การอ้างอิงที่ชี้ไปที่วัตถุไปยังวัตถุใหม่เช่นรหัสต่อไปนี้:
Object obj = วัตถุใหม่ (); obj = null; object obj1 = วัตถุใหม่ (); object obj2 = วัตถุใหม่ (); obj1 = obj2;
2) การอ้างอิงท้องถิ่นไปยังวัตถุที่ชี้ไปเช่นรหัสต่อไปนี้:
เป็นโมฆะ fun () {...... สำหรับ (int i = 0; i <10; i ++) {object obj = วัตถุใหม่ (); System.out.println (obj.getClass ()); -ทุกครั้งที่มีการดำเนินการลูปวัตถุวัตถุที่สร้างขึ้นจะกลายเป็นวัตถุรีไซเคิล
3) การอ้างอิงที่อ่อนแอเท่านั้นที่เกี่ยวข้องกับวัตถุเช่น:
Weakreference <string> wr = new beakreference <string> (สตริงใหม่ ("โลก"));2. อัลกอริทึมการรวบรวมขยะทั่วไป
หลังจากพิจารณาว่าขยะที่สามารถนำกลับมาใช้ใหม่ได้แล้วตัวเก็บขยะต้องทำคือการเริ่มต้นการเก็บขยะ แต่ปัญหาหนึ่งที่เกี่ยวข้องคือวิธีเก็บขยะได้อย่างมีประสิทธิภาพ เนื่องจากข้อกำหนดของเครื่องเสมือน Java ไม่ได้กำหนดกฎระเบียบที่ชัดเจนเกี่ยวกับวิธีการใช้เครื่องรวบรวมขยะเครื่องเสมือนจริงของผู้ผลิตแต่ละรายสามารถใช้ตัวเก็บขยะในรูปแบบที่แตกต่างกันดังนั้นแนวคิดหลักของอัลกอริทึมการรวบรวมขยะทั่วไปหลายประการเท่านั้นที่นี่
1.Mark-Sweep (MARK-CLEAR) อัลกอริทึม
นี่คืออัลกอริทึมการรวบรวมขยะขั้นพื้นฐานที่สุด เหตุผลที่มีการกล่าวกันว่าเป็นพื้นฐานที่สุดคือมันเป็นวิธีที่ง่ายที่สุดในการใช้งานและความคิดที่ง่ายที่สุด อัลกอริทึมการล้างเครื่องหมายแบ่งออกเป็นสองขั้นตอน: ขั้นตอนการทำเครื่องหมายและขั้นตอนการล้าง ภารกิจของขั้นตอนการทำเครื่องหมายคือการทำเครื่องหมายวัตถุทั้งหมดที่ต้องรีไซเคิลและขั้นตอนการล้างคือการรีไซเคิลพื้นที่ที่ถูกครอบครองโดยวัตถุที่ทำเครื่องหมายไว้ กระบวนการเฉพาะแสดงในรูปด้านล่าง:
มันสามารถมองเห็นได้ง่ายจากรูปที่อัลกอริทึมการล้างเครื่องหมายนั้นง่ายต่อการใช้งาน แต่มีปัญหาร้ายแรงที่ง่ายต่อการสร้างชิ้นส่วนหน่วยความจำ ชิ้นส่วนมากเกินไปอาจทำให้ไม่สามารถหาพื้นที่เพียงพอเมื่อจัดสรรพื้นที่สำหรับวัตถุขนาดใหญ่ในกระบวนการที่ตามมาและกระตุ้นการดำเนินการรวบรวมขยะใหม่ล่วงหน้า
2. การคัดลอก (คัดลอก) อัลกอริทึม
เพื่อที่จะแก้ปัญหาข้อบกพร่องของอัลกอริทึมมาร์ค-กวาดได้เสนออัลกอริทึมการคัดลอก มันแบ่งหน่วยความจำที่มีอยู่เป็นสองชิ้นที่มีขนาดเท่ากันโดยใช้เพียงชิ้นเดียวในแต่ละครั้ง เมื่อหน่วยความจำชิ้นนี้หมดแล้วให้คัดลอกวัตถุที่ยังมีชีวิตไปยังอีกชิ้นหนึ่งจากนั้นทำความสะอาดพื้นที่หน่วยความจำที่ใช้ในครั้งเดียวเพื่อให้ปัญหาการกระจายตัวของหน่วยความจำจะไม่เกิดขึ้น กระบวนการเฉพาะแสดงในรูปด้านล่าง:
แม้ว่าอัลกอริทึมนี้จะใช้งานได้ง่าย แต่ก็มีประสิทธิภาพในการทำงานและไม่ง่ายที่จะสร้างการกระจายตัวของหน่วยความจำ แต่ก็มีราคาแพงในการใช้พื้นที่หน่วยความจำเนื่องจากหน่วยความจำที่สามารถใช้งานได้ลดลงเหลือครึ่งหนึ่งของต้นฉบับ
เห็นได้ชัดว่าประสิทธิภาพของอัลกอริทึมการคัดลอกมีส่วนเกี่ยวข้องกับจำนวนวัตถุที่รอดชีวิต หากมีวัตถุที่รอดชีวิตมากมายประสิทธิภาพของอัลกอริทึมการคัดลอกจะลดลงอย่างมาก
อัลกอริทึม 3. มาร์ค-คอมแพค
เพื่อแก้ข้อบกพร่องของอัลกอริทึมการคัดลอกและใช้ประโยชน์จากพื้นที่หน่วยความจำอย่างเต็มที่ อัลกอริทึมทำเครื่องหมายเช่นเดียวกับมาร์คกวาด แต่หลังจากทำเครื่องหมายเสร็จแล้วมันจะไม่ทำความสะอาดวัตถุรีไซเคิลโดยตรง แต่ย้ายวัตถุที่มีชีวิตทั้งหมดไปยังปลายด้านหนึ่งแล้วทำความสะอาดหน่วยความจำนอกขอบเขตสิ้นสุด กระบวนการเฉพาะแสดงในรูปด้านล่าง:
4. อัลกอริทึมการรวบรวม Generational
อัลกอริทึมการสร้างการสร้างปัจจุบันถูกใช้โดยนักสะสมขยะ JVM ส่วนใหญ่ แนวคิดหลักของมันคือการแบ่งหน่วยความจำออกเป็นหลายภูมิภาคตามวงจรชีวิตของการอยู่รอดของวัตถุ โดยทั่วไปพื้นที่กองจะแบ่งออกเป็นคนรุ่นเก่าและคนรุ่นใหม่ ลักษณะของรุ่นเก่าคือมีเพียงวัตถุจำนวนน้อยที่ต้องรีไซเคิลทุกครั้งที่เก็บขยะในขณะที่ลักษณะของคนรุ่นใหม่คือวัตถุจำนวนมากต้องรีไซเคิลทุกครั้งที่เก็บขยะ จากนั้นอัลกอริทึมการรวบรวมที่เหมาะสมที่สุดสามารถนำมาใช้ตามลักษณะของรุ่นต่าง ๆ
ในปัจจุบันนักสะสมขยะส่วนใหญ่ใช้อัลกอริทึมการคัดลอกสำหรับคนรุ่นใหม่เพราะในรุ่นใหม่วัตถุส่วนใหญ่จะต้องรีไซเคิลทุกครั้งที่รวบรวมการรวบรวมขยะซึ่งหมายความว่าจำนวนการดำเนินการที่ต้องคัดลอกมีขนาดค่อนข้างเล็ก แต่ในความเป็นจริงพื้นที่ของคนรุ่นใหม่ โดยทั่วไปแล้วคนรุ่นใหม่จะแบ่งออกเป็นพื้นที่อีเด็นขนาดใหญ่และพื้นที่ผู้รอดชีวิตขนาดเล็กสองแห่ง ทุกครั้งที่มีการใช้พื้นที่ Eden และหนึ่งในช่องว่างผู้รอดชีวิตเมื่อรีไซเคิลวัตถุที่ยังคงรอดชีวิตใน Eden และ Survivor จะถูกคัดลอกไปยังพื้นที่ผู้รอดชีวิตอื่นและจากนั้น Eden และ Survivor Spaces ที่เพิ่งใช้ถูกทำความสะอาด
เนื่องจากวัยชราคือมีเพียงวัตถุจำนวนน้อยเท่านั้นที่ถูกนำกลับมาใช้ใหม่ทุกครั้งจึงใช้อัลกอริทึมที่มีขนาดกะทัดรัด
โปรดทราบว่ามีรุ่นอื่นนอกพื้นที่ฮีปซึ่งเป็นการสร้างแบบถาวรซึ่งใช้ในการจัดเก็บคลาสคลาสค่าคงที่คำอธิบายวิธีการ ฯลฯ การรีไซเคิลรุ่นถาวรส่วนใหญ่รีไซเคิลสองส่วน: ค่าคงที่ที่ถูกทิ้งและคลาสที่ไร้ประโยชน์
3. นักสะสมขยะทั่วไป
อัลกอริทึมการรวบรวมขยะเป็นพื้นฐานทางทฤษฎีของการรีไซเคิลหน่วยความจำและตัวเก็บขยะคือการใช้งานเฉพาะของการรีไซเคิลหน่วยความจำ ต่อไปนี้เป็นคำอธิบายของนักสะสมขยะหลายตัวที่จัดทำโดยเครื่องฮอตสปอต (JDK 7) เครื่องเสมือน ผู้ใช้สามารถรวมนักสะสมที่ใช้ในแต่ละยุคสมัยตามความต้องการของตนเอง
1. เก่า/อนุกรม
นักสะสมเก่าแบบอนุกรม/อนุกรมเป็นนักสะสมพื้นฐานและเก่าแก่ที่สุด มันเป็นตัวสะสมเธรดเดียวและต้องหยุดกระทู้ผู้ใช้ทั้งหมดทั้งหมดเมื่อมันทำการรวบรวมขยะ Serial Collector เป็นนักสะสมสำหรับคนรุ่นใหม่โดยใช้อัลกอริทึมการคัดลอกและตัวสะสมเก่าอนุกรมเป็นนักสะสมสำหรับคนรุ่นเก่าโดยใช้อัลกอริทึมมาร์คคอมแพค ข้อได้เปรียบคือมันง่ายและมีประสิทธิภาพ แต่ข้อเสียของมันคือมันจะทำให้ผู้ใช้หยุดชั่วคราว
2. พาร์นนิว
Parnew Collector เป็นรุ่นมัลติเธรดของนักสะสมอนุกรมที่ใช้หลายเธรดสำหรับการรวบรวมขยะ
3.
นักสะสม Scavenge แบบขนานเป็นรุ่นใหม่ของนักสะสม multithreaded (นักสะสมคู่ขนาน) ไม่จำเป็นต้องหยุดเธรดผู้ใช้อื่น ๆ ระหว่างการรีไซเคิล มันใช้อัลกอริทึมการคัดลอก นักสะสมนี้แตกต่างจากนักสะสมสองคนแรก ส่วนใหญ่จะได้รับปริมาณงานที่ควบคุมได้
4. คู่ขนาน
แบบขนานเก่าเป็นรุ่นเก่าของนักสะสม Scavenge (คู่ขนาน) โดยใช้อัลกอริทึมมัลติเธรดและเครื่องหมายคอมแพค
5. ซม.
CMS (MARK Sweep ปัจจุบัน) นักสะสมเป็นนักสะสมที่มุ่งเป้าไปที่เวลาหยุดพักการกู้คืนที่สั้นที่สุด มันเป็นตัวสะสมที่เกิดขึ้นพร้อมกันที่ใช้อัลกอริทึมมาร์ค-กวาด
6.G1
G1 Collector เป็นความสำเร็จที่ทันสมัยที่สุดในการพัฒนาเทคโนโลยีนักสะสมในปัจจุบัน เป็นตัวสะสมสำหรับแอปพลิเคชันฝั่งเซิร์ฟเวอร์ที่สามารถใช้ประโยชน์จากสภาพแวดล้อมแบบมัลติ CPU และหลายคอร์ได้อย่างเต็มที่ ดังนั้นจึงเป็นตัวสะสมแบบขนานและพร้อมกันและสามารถสร้างแบบจำลองเวลาหยุดชั่วคราวที่คาดการณ์ได้
นี่คือบางสิ่งเกี่ยวกับการจัดสรรหน่วยความจำ:
ในทิศทางทั่วไปการจัดสรรหน่วยความจำของวัตถุจะถูกจัดสรรบนกอง วัตถุส่วนใหญ่ได้รับการจัดสรรในพื้นที่ Eden รุ่นใหม่และจากอวกาศและในบางกรณีพวกเขาจะได้รับการจัดสรรโดยตรงในวัยชรา หากพื้นที่ของพื้นที่ Eden รุ่นใหม่และจากอวกาศไม่เพียงพอ GC จะเริ่มต้นขึ้น หากดำเนินการ GC พื้นที่ Eden และจากอวกาศสามารถรองรับวัตถุและวางไว้ในพื้นที่ Eden และจากอวกาศ
ในระหว่างกระบวนการ GC วัตถุที่รอดชีวิตในพื้นที่อีเด็นและจากอวกาศจะถูกย้ายไปยังอวกาศและจากนั้นพื้นที่อีเด็นและจากอวกาศจะถูกทำความสะอาด หากพื้นที่ไม่เพียงพอที่จะเก็บวัตถุในระหว่างการทำความสะอาดมันจะย้ายวัตถุไปสู่วัยชรา หลังจาก GC แล้วจะใช้พื้นที่ Eden และพื้นที่ ครั้งต่อไปที่คุณ GC วัตถุที่รอดชีวิตจะถูกคัดลอกจากอวกาศและลูปจะถูกทำซ้ำ เมื่อวัตถุหลบหนี GC หนึ่งครั้งในพื้นที่ผู้รอดชีวิตอายุของวัตถุจะเพิ่มขึ้น 1 โดยค่าเริ่มต้นถ้าวัตถุมีอายุ 15 ปีมันจะย้ายไปจนถึงวัยกลางคนของวัยชรา
โดยทั่วไปแล้ววัตถุขนาดใหญ่จะได้รับการจัดสรรโดยตรงให้กับวัยชรา วัตถุขนาดใหญ่ที่เรียกว่าวัตถุที่ต้องการพื้นที่เก็บข้อมูลต่อเนื่องจำนวนมาก ประเภทที่พบมากที่สุดของวัตถุขนาดใหญ่คืออาร์เรย์ขนาดใหญ่เช่น:
ไบต์ [] data = byte ใหม่ [4*1024*1024]
พื้นที่เก็บข้อมูลประเภทนี้โดยทั่วไปจะถูกจัดสรรโดยตรงในผู้สูงอายุ
แน่นอนว่ากฎการจัดสรรไม่ได้รับการแก้ไข 100% ซึ่งขึ้นอยู่กับการรวมกันของตัวเก็บขยะประเภทใดและพารามิเตอร์ที่เกี่ยวข้องของ JVM กำลังใช้อยู่
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น