พื้นที่หน่วยความจำ Java และตัวรวบรวมขยะ

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

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

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

สิ่งสุดท้ายคือหลังจากทำเครื่องหมายและกวาดบางครั้งการบดอัดก็เสร็จสิ้น gc รู้ได้อย่างไรว่าการอ้างอิงถึงวัตถุที่ถูกย้ายใดที่ต้องได้รับการอัปเดต หากเรามีโปรแกรมที่มีเธรดหลายพันเธรดพร้อมเฟรมสแต็กขนาดใหญ่และฮีปที่ใช้เป็นกิกะไบต์ มันมีโครงสร้างภายในที่มีข้อมูลนั้นอยู่ในรูปแบบของแผนที่หรืออะไรสักอย่าง?

ขอบคุณ!


person alobodzk    schedule 25.09.2014    source แหล่งที่มา


คำตอบ (3)


YoungGen/OldGen & PermGen คือสามพื้นที่ที่มี Java Heap อาศัยอยู่ JVM มีความรอบรู้เกี่ยวกับขอบเขตของแต่ละรายการ

  1. ในขณะที่รวบรวมขยะ GC จะตัดสินใจว่าจะรันพื้นที่ใดก่อน จากนั้นจึงระบุรากของ GC ของแต่ละวัตถุในพื้นที่นั้น ไม่ว่าวัตถุจะอายุน้อยหรือเก่าก็ตามจะถูกระบุโดย Space ที่วัตถุนั้นอยู่ในฮีป GC รักษาสถานะของออบเจ็กต์แต่ละรายการเช่นเดียวกับจำนวนรอบ GC ที่แต่ละออบเจ็กต์รอดชีวิตมาได้ ซึ่งทำให้ GC สามารถประมาณได้ว่าเวลาเหมาะสมที่จะย้ายออบเจ็กต์จากรุ่นเล็กไปรุ่นเก่าหรือไม่

  2. กราฟวัตถุจะตัดสินว่าวัตถุ Gen รุ่นเยาว์ถูกอ้างอิงโดยการอ้างอิงรุ่นเก่าหรือไม่

  3. หากวัตถุถูกบีบอัด ข้อมูลอ้างอิงก็จะได้รับการอัปเดตด้วย สิ่งนี้จะเกิดขึ้นเช่นกันเมื่อวัตถุย้ายจาก Young > Old Gen

person Geek    schedule 25.09.2014
comment
ขอบคุณ @Geek! อีกประการหนึ่ง GC ดำเนินการรวบรวมเล็กน้อยอย่างไร มันไปกับการเลือกราก GC ด้วยหรือไม่? ฉันเข้าใจว่าในคอลเลกชันย่อย คุณไม่ต้องการสัมผัสสิ่งเหล่านั้นในรุ่นเก่า แล้ว GC จะตัดสินใจได้อย่างไรว่าควรจัดการรูต GC ใดในคอลเลกชันย่อย - person alobodzk; 30.09.2014

คำตอบขึ้นอยู่กับอัลกอริธึม GC ดังนั้นคุณจะพบคำตอบที่หลากหลาย

GC รู้ได้อย่างไรว่าวัตถุไหนอายุน้อย และวัตถุไหนเก่า? จะรู้ได้อย่างไรว่าวัตถุพื้นที่หน่วยความจำใดอยู่ใน?

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

gc รู้ได้อย่างไรว่าวัตถุในรุ่นใหม่ไม่ได้อ้างอิงโดยวัตถุในรุ่นเก่าหรือโดยการอ้างอิงแบบคงที่จากพื้นที่วิธีการ

อัลกอริธึม GC บางตัวจะทำการสแกนออบเจ็กต์ทั้งหมดในฮีปโดยสมบูรณ์ คนอื่นๆ อาศัยการสังเกตว่าจำนวนผู้อ้างอิงตั้งแต่รุ่นเก๋าไปจนถึงรุ่นเยาว์นั้นค่อนข้างต่ำ ดังนั้น JVM จึงติดตามพวกเขาและใช้เป็นรากฐานในการทำเครื่องหมาย กลไกนี้มักจะเป็นระบบบัตรคะแนน และเป็นเหตุผลว่าทำไมอัลกอริธึม GC บางตัวที่มีพื้นที่บรรพบุรุษขนาดใหญ่มากอาจทำให้ GC ของพื้นที่อายุน้อยช้าลง เพราะทุกบัตรคะแนนของทุกวัตถุจะต้องได้รับการตรวจสอบเพื่อดูว่าจะสามารถชี้กลับไปยังคนรุ่นใหม่ได้หรือไม่

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

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

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

person Chris K    schedule 25.09.2014
comment
ขอบคุณคริส! ฉันขอให้คุณตรวจสอบคำถามของฉันในความคิดเห็นของคำตอบของ Geek ได้ไหม - person alobodzk; 30.09.2014
comment
@alobodzk เราสามารถเจาะจงได้มากขึ้นหากเราเลือกอัลกอริธึมเดียว มาดู CMS กันดีกว่า การใช้ Concurrent Mark and Sweep ของ Oracle Hotspot GC รุ่นเยาว์ของพวกเขาใช้รากปกติ นั่นคือ เธรด การเรียกแบบเนทีฟ และอื่นๆ สำหรับรุ่นรุ่นเก่าถึงรุ่นใหม่จะมีบิตจำนวนมากที่เรียงตามที่อยู่หน่วยความจำทุกรายการในเจนเนอเรชั่นเก่า แต่ละบิตบอกว่าอาจเป็นตัวชี้ไปยังรุ่นเยาว์ (แต่อาจเป็นผลบวกลวง) รุ่นเยาว์สแกนสิ่งนี้และหยั่งรากจากที่นั่น สิ่งเหล่านี้เรียกว่า 'ตารางไพ่' - person Chris K; 30.09.2014
comment
สามารถอ่านรายละเอียดดีๆ เกี่ยวกับตารางไพ่ได้ที่นี่: เชิงกล-sympathy.blogspot.co.uk/2013/07/ - person Chris K; 30.09.2014
comment
ขอบคุณ! คุณพูดถึง CMS แต่ฉันเคยเห็นวิดีโอบน youtube กับผู้ชายจาก Azul Systems บน GC และเขาบอกว่า jvms ส่วนใหญ่ใช้การรวบรวมสำเนาในคอลเลกชันย่อยซึ่งควรจะเป็นถ้าฉันเข้าใจอย่างถูกต้องโดยไม่มีเฟสทำเครื่องหมาย gc เป็นเพียงการคัดลอก วัตถุมีชีวิตในพื้นที่หน่วยความจำใหม่และฉันไม่เข้าใจว่ามันทำงานได้อย่างไร คุณจะบอกได้อย่างไรว่าวัตถุใดยังอายุน้อยโดยไม่ต้องผ่านกราฟและตรวจสอบที่อยู่อ้างอิงของมัน - person alobodzk; 30.09.2014
comment
@alobodzk ไม่มีเฟสมาร์คเหรอ? เราต้องระวังคำศัพท์ที่นี่ CMS นั้นไม่ใช่ตัวรวบรวมพื้นที่รุ่นเยาว์ใน JVM ของ Oracle มันอาศัยนักสะสมอวกาศรุ่นเยาว์ STW (Stop The World) แบบดั้งเดิม CMS มี 'เฟส' ที่เรียกว่า 'เฟสมาร์ค' อย่างชัดเจน และเฟสมาร์คนั้นมีทั้งแบบขนานและเกิดขึ้นพร้อมกัน ฉันสงสัยว่าวิดีโอที่คุณดูอ้างถึงเวอร์ชันของคนรุ่นใหม่ว่าเป็น STW (กล่าวคือ ไม่สอดคล้องกับเธรดของแอปพลิเคชัน) แต่นั่นไม่ได้หมายความว่า alg ในอวกาศรุ่นเยาว์ไม่สามารถเดินไปตามกองเพื่อระบุวัตถุที่มีชีวิตได้ มันไม่อย่างแน่นอน - person Chris K; 01.10.2014

  1. ทุกครั้งที่ GC ตรวจสอบว่าสามารถรวบรวมวัตถุได้หรือไม่ มันจะเพิ่มตัวนับในวัตถุ ซึ่งจะบอกว่า GC เยี่ยมชมวัตถุนั้นกี่ครั้ง นั่นเป็นวิธีที่ง่ายที่สุดในการบอกได้ว่าเมื่อใดที่จำเป็นต้องย้ายวัตถุจากรุ่นเยาว์ไปสู่รุ่นที่ดำรงตำแหน่ง แต่สำหรับการรู้ว่าวัตถุนั้นอยู่ในพื้นที่ใด ก็สามารถใช้ที่อยู่ของวัตถุนั้นมาคำนวณได้ (เช่น JVM จะบอกว่าที่อยู่หน่วยความจำระหว่าง 0-100 คือคนรุ่นใหม่ 101+ คือรุ่นที่ดำรงตำแหน่ง)
  2. แม้ในระหว่างการรวบรวมเล็กน้อย กราฟวัตถุทั้งหมดจะถูกสำรวจเพื่อตรวจสอบการอ้างอิง อย่างน้อยในทางทฤษฎีนั่นคือสิ่งที่เกิดขึ้น จะมีการเพิ่มประสิทธิภาพในทางปฏิบัติ แต่แนวคิดทั่วไปก็คือสิ่งนี้
  3. เนื่องจากขั้นตอนแรกคือการสร้างกราฟของข้อมูลอ้างอิง ข้อมูลดังกล่าวจึงยังคงอยู่ในขั้นตอนการบดอัด แต่ใช่แล้ว การอัดฮีปขนาดกิกะไบต์ใช้เวลานาน
person biziclop    schedule 25.09.2014