ข้อความบันทึก Java Garbage Collection


96

ฉันได้กำหนดค่า java ให้ทิ้งข้อมูลการรวบรวมขยะลงในบันทึก ( verbose GC ) ฉันไม่แน่ใจว่ารายการรวบรวมขยะในบันทึกหมายถึงอะไร ตัวอย่างของรายการเหล่านี้แสดงไว้ด้านล่าง ฉันค้นหาในGoogleและไม่พบคำอธิบายที่ชัดเจน

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

  1. PSYoungGen หมายถึงอะไร? ฉันคิดว่ามันมีส่วนเกี่ยวข้องกับคนรุ่นก่อน (อายุน้อยกว่า) แต่อะไรกันแน่?
  2. อะไรคือความแตกต่างระหว่างเลขสามตัวที่สองกับตัวแรก?
  3. เหตุใดจึงมีการระบุชื่อ (PSYoungGen) สำหรับตัวเลขสามตัวแรก แต่ไม่ใช่ตัวที่สอง
  4. ตัวเลขแต่ละตัว (ขนาดหน่วยความจำ) ในทริปเปิ้ลหมายถึงอะไร ตัวอย่างเช่นใน 109884K-> 14201K (139904K) คือหน่วยความจำก่อน GC 109884k จากนั้นจะลดลงเหลือ 14201K เลขสามเกี่ยวข้องกันอย่างไร? ทำไมเราต้องใช้ตัวเลขชุดที่สอง

8109.128: [GC [PSYoungGen: 109884K-> 14201K (139904K)] 691015K-> 595332K (1119040K), 0.0454530 วินาที]

8112.111: [GC [PSYoungGen: 126649K-> 15528K (142336K)] 707780K-> 605892K (1121472K), 0.0934560 วินาที]

8112.802: [GC [PSYoungGen: 130344K-> 3732K (118592K)] 720708K-> 607895K (1097728K), 0.0682690 วินาที]


กองทั้งหมด, ส่วนของฮีปรุ่นเยาว์, gc เล็กน้อยสำหรับวิธีการทำงานของ gc ตรวจสอบเช่น cubrid.org/blog/dev-platform/…
MarianP

คำตอบ:


90

ส่วนใหญ่จะอธิบายไว้ในคู่มือการปรับแต่ง GC (ซึ่งคุณควรอ่านต่อไป)

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

[GC 325407K->83000K(776768K), 0.2300771 secs]
[GC 325816K->83372K(776768K), 0.2454258 secs]
[Full GC 267628K->83769K(776768K), 1.8479984 secs]

ที่นี่เราจะเห็นคอลเล็กชันย่อยสองรายการตามด้วยคอลเล็กชันหลัก ตัวเลขก่อนและหลังลูกศร (เช่น325407K->83000Kจากบรรทัดแรก) ระบุขนาดรวมของวัตถุที่มีชีวิตก่อนและหลังการเก็บขยะตามลำดับ หลังจากการรวบรวมเล็กน้อยขนาดจะรวมวัตถุบางอย่างที่เป็นขยะ (ไม่มีชีวิตอีกต่อไป) แต่ไม่สามารถเรียกคืนได้ วัตถุเหล่านี้มีอยู่ในรุ่นที่ครอบครองหรืออ้างอิงจากรุ่นที่ดำรงอยู่หรือถาวร

ตัวเลขถัดไปในวงเล็บ (เช่น(776768K)จากบรรทัดแรกอีกครั้ง) คือขนาดคอมมิตของฮีป: จำนวนพื้นที่ที่ใช้งานได้สำหรับอ็อบเจ็กต์ java โดยไม่ต้องร้องขอหน่วยความจำเพิ่มเติมจากระบบปฏิบัติการ โปรดทราบว่าหมายเลขนี้ไม่รวมช่องว่างผู้รอดชีวิตเพียงช่องเดียวเนื่องจากสามารถใช้ได้เพียงช่องเดียวในช่วงเวลาใดเวลาหนึ่งและยังไม่รวมการสร้างแบบถาวรซึ่งเก็บข้อมูลเมตาที่ใช้โดยเครื่องเสมือน

รายการสุดท้ายในบรรทัด (เช่น0.2300771 secs) ระบุเวลาที่ใช้ในการรวบรวม ในกรณีนี้ประมาณหนึ่งในสี่ของวินาที

รูปแบบสำหรับคอลเลกชันหลักในบรรทัดที่สามจะคล้ายกัน

รูปแบบของผลลัพธ์ที่ผลิตโดย-verbose:gcอาจมีการเปลี่ยนแปลงในรุ่นในอนาคต

ฉันไม่แน่ใจว่าทำไมถึงมี PSYoungGen อยู่ในตัวคุณ คุณเปลี่ยนคนเก็บขยะหรือเปล่า


จะหาไฟล์บันทึก gc ได้ที่ไหน
Mr Lou

7
คำตอบนี้ไม่ได้ตอบคำถามเดิมจริงๆ ฉันรู้สึกว่าคำตอบของ michaeljoseph ดีกว่า มันตอบคำถามที่ถามโดยอีธานและทำงานได้ดีกว่าในการทำลายตัวอย่างเดิม ในขณะที่มีสองประเด็นในคำตอบของเขา (ลิงก์ของเขาเสียชีวิตแล้วและ rafa.ferreria ได้ชี้ให้เห็นถึงปัญหาอื่น ๆ ) แต่ไม่เพียงแค่ทำให้เอกสาร Oracle กลับมาอีกครั้ง
Dirk

127
  1. PSYoungGen หมายถึงเครื่องเก็บขยะที่ใช้สำหรับการเก็บรวบรวมรายย่อย PS ย่อมาจาก Parallel Scavenge
  2. ตัวเลขชุดแรกคือขนาดก่อน / หลังของคนรุ่นใหม่และชุดที่สองใช้สำหรับกองทั้งหมด (กำลังวินิจฉัยปัญหาการเก็บขยะรายละเอียดรูปแบบ)
  3. ชื่อระบุการสร้างและตัวรวบรวมที่เป็นปัญหาชุดที่สองใช้สำหรับฮีปทั้งหมด

ตัวอย่างของ GC แบบเต็มที่เกี่ยวข้องยังแสดงให้เห็นนักสะสมที่ใช้สำหรับคนรุ่นเก่าและรุ่นถาวร:

3.757: [Full GC [PSYoungGen: 2672K->0K(35584K)] 
            [ParOldGen: 3225K->5735K(43712K)] 5898K->5735K(79296K) 
            [PSPermGen: 13533K->13516K(27584K)], 0.0860402 secs]

ในที่สุดการแบ่งหนึ่งบรรทัดของผลลัพธ์บันทึกตัวอย่างของคุณ:

8109.128: [GC [PSYoungGen: 109884K->14201K(139904K)] 691015K->595332K(1119040K), 0.0454530 secs]
  • 107Mbใช้ก่อน GC, 14Mbใช้หลัง GC, max young generation ขนาด137Mb
  • ฮีป675Mb ที่ใช้ก่อน GC, 581Mbฮีปที่ใช้หลัง GC, ขนาดฮีปสูงสุด1Gb
  • minor GC เกิดขึ้น 8109.128วินาทีนับตั้งแต่เริ่ม JVM และใช้เวลา0.04วินาที

8
เป็นเพียงความคิดเห็นเล็กน้อยค่าระหว่าง '()' ไม่ใช่ขนาดสูงสุดตลอดกาลคือขนาดสูงสุดในขณะนั้น หาก GC ไม่สามารถเพิ่มฮีปให้น้อยลงได้ก็จะต้องมีพื้นที่ จำกัด เพิ่มขึ้นสำหรับระบบปฏิบัติการและค่านี้จะเพิ่มขึ้น เคารพแน่นอนขีด จำกัด ที่กำหนดไว้เมื่อ: -Xmx
rafa.ferreira

@ rafa.ferreira ฉันคิดว่าค่าใน paranthesis เช่น 1119040K คือขนาดฮีปที่กำหนด ฉันไม่คิดว่า GC จะพิมพ์ขนาด 'max heap' ที่ใดก็ได้ อ้างอิง 1และอ้างอิง 2
rohitmohta

23

ฉันแค่อยากจะพูดถึงว่าเราสามารถรับบันทึก GC โดยละเอียดด้วยไฟล์

-XX:+PrintGCDetails 

พารามิเตอร์. จากนั้นคุณจะเห็นผลลัพธ์ PSYoungGen หรือ PSPermGen เหมือนในคำตอบ

นอกจากนี้ยัง-Xloggc:gc.logดูเหมือนว่าจะสร้างการส่งออกเช่นเดียวกัน-verbose:gcแต่คุณสามารถระบุไฟล์ที่ส่งออกในครั้งแรก

ตัวอย่างการใช้งาน:

java -Xloggc:./memory.log -XX:+PrintGCDetails Memory

เพื่อให้เห็นภาพข้อมูลได้ดีขึ้นคุณสามารถลองใช้gcviewer (เวอร์ชันล่าสุดสามารถพบได้ในgithub )

โปรดเขียนพารามิเตอร์ให้ถูกต้องด้วยฉันลืม "+" และ JBoss ของฉันจะไม่เริ่มทำงานโดยไม่มีข้อความแสดงข้อผิดพลาด!


3
โปรดทราบว่า gc.log จะถูกเขียนทับเมื่อเริ่มต้น java ใหม่ (เช่นถ้าคุณรีสตาร์ทเครื่อง tomcat เนื่องจากมีปัญหาเกี่ยวกับหน่วยความจำและคุณชอบที่จะเห็น gc.log นั้น) หรืออย่างน้อยก็ถ้าคุณหมุนบันทึก GC มีตัวเลือกอื่น ๆ อีกมากมายที่ควบคุมการบันทึก gc ดูoracle.com/technetwork/articles/java/vmoptions-jsp-140102.html โดยเฉพาะอย่างยิ่งพิจารณา-XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=<some number of files> -XX:GCLogFileSize=<some size> -XX:+PrintTenuringDistribution
Dan Pritts
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.