พูลหน่วยความจำ java ถูกแบ่งอย่างไร?


224

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

Heap Memory Usage
Non-Heap Memory Usage
Memory Pool “Eden Space”
Memory Pool “Survivor Space”
Memory Pool “Tenured Gen”
Memory Pool “Code Cache”
Memory Pool “Perm Gen”

ความแตกต่างระหว่างพวกเขาคืออะไร?


สมมติว่าคุณกำลังใช้ Sun JDK คำตอบที่ดีที่สุดจะพบได้ในเอกสารประกอบของพวกเขา: การปรับแต่ง Garbage Collection (JDK 1.5)และGarbage Collection FAQ (JDK 1.4)
kdgregory

คำตอบ:


327

หน่วยความจำกอง

หน่วยความจำฮีปคือพื้นที่ข้อมูลรันไทม์ซึ่ง Java VM จัดสรรหน่วยความจำสำหรับอินสแตนซ์และอาร์เรย์ของคลาสทั้งหมด ฮีปอาจมีขนาดคงที่หรือแปรผัน ตัวรวบรวมขยะคือระบบจัดการหน่วยความจำอัตโนมัติที่เรียกคืนหน่วยความจำฮีพสำหรับวัตถุ

  • Eden Space : พูลที่หน่วยความจำเริ่มแรกจัดสรรให้กับวัตถุส่วนใหญ่

  • พื้นที่ผู้รอดชีวิต : สระว่ายน้ำที่มีวัตถุที่รอดชีวิตจากการเก็บขยะในพื้นที่เอเดน

  • Generation TenuredหรือGen เดิม : พูลที่มีวัตถุที่มีอยู่ในพื้นที่ของผู้รอดชีวิตมาระยะหนึ่งแล้ว

หน่วยความจำไม่ใช่ฮีป

หน่วยความจำ Non-heap รวมถึงพื้นที่วิธีที่แบ่งใช้ระหว่างเธรดและหน่วยความจำทั้งหมดที่จำเป็นสำหรับการประมวลผลภายในหรือการปรับให้เหมาะสมสำหรับ Java VM มันเก็บโครงสร้างต่อคลาสเช่นสระว่ายน้ำคงที่ runtime, ข้อมูลและวิธีการและรหัสสำหรับวิธีการและการก่อสร้าง พื้นที่เมธอดเป็นส่วนหนึ่งของ heap อย่างมีเหตุผล แต่ขึ้นอยู่กับการนำไปใช้งาน Java VM อาจไม่ได้เก็บรวบรวมขยะหรือทำให้กระชับ เช่นเดียวกับหน่วยความจำฮีปพื้นที่เมธอดอาจมีขนาดคงที่หรือขนาดผันแปร หน่วยความจำสำหรับพื้นที่เมธอดไม่จำเป็นต้องต่อเนื่องกัน

  • การสร้างแบบถาวร : พูลที่มีข้อมูลการสะท้อนกลับทั้งหมดของเครื่องเสมือนเองเช่นวัตถุคลาสและวิธีการ ด้วย Java VMs ที่ใช้การแบ่งใช้คลาสของข้อมูลการสร้างนี้แบ่งออกเป็นพื้นที่อ่านอย่างเดียวและอ่านเขียน

  • โค้ดแคช : HotSpot Java VM ยังมีแคชโค้ดซึ่งมีหน่วยความจำที่ใช้สำหรับการคอมไพล์และการจัดเก็บโค้ดเนทีฟ

นี่เอกสารบางอย่างเกี่ยวกับวิธีการใช้ JConsole


4
ฉันไม่แน่ใจว่า @dfa ถูกต้องทั้งหมดเนื่องจาก Java Virtual Machine Specification ระบุอย่างชัดเจนว่า: "แม้ว่าพื้นที่ของเมธอดจะเป็นส่วนหนึ่งของ heap แต่การปรับใช้อย่างง่ายอาจเลือกที่จะไม่เก็บขยะหรือทำให้กะทัดรัด" อย่างไรก็ตามเป็นที่ชัดเจนว่า jconsole แสดง Code Cache และ Permanent Generation เป็น Non-Heap ซึ่งดูเหมือนจะขัดแย้งกับสเปค ใครช่วยอธิบายเพิ่มเติมเกี่ยวกับความขัดแย้งนี้ได้หรือไม่?
James Bloom

@ JamesBloom - ฉันสงสัยเหมือนกัน แม้ว่าคำจำกัดความพื้นฐานจะระบุว่าพูลของหน่วยความจำประเภทใด (heap / non-heap) แต่มันสามารถเปลี่ยนแปลงได้หรือไม่ที่เป็นสถานะอย่างชัดเจน?
Umang Desai

2
เอกสารนี้มีชื่อเล่น semistic จาก: docs.intergral.com/pages/viewpage.action?pageId=22478944เอกสารนี้มีข้อมูลที่ดีอื่น ๆ เกี่ยวกับ JVM ที่คุ้มค่ากับการดู
Steve Siebert

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

และไม่ลืมที่สแต็ค (บนฝั่งที่ไม่ใช่กอง) :)
ฟัน Seer

70

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

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

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

นอกจากนี้ยังมีรุ่นที่สี่เรียกว่ารุ่นถาวรหรือ PermGen อ็อบเจ็กต์ที่อยู่ที่นี่ไม่มีสิทธิ์ถูกรวบรวมขยะและโดยทั่วไปจะมีสถานะที่ไม่เปลี่ยนรูปแบบซึ่งจำเป็นสำหรับ JVM ในการเรียกใช้เช่นข้อกำหนดคลาสและพูลคงที่ของสตริง โปรดทราบว่าพื้นที่ PermGen มีการวางแผนที่จะลบออกจาก Java 8 และจะถูกแทนที่ด้วยพื้นที่ใหม่ที่เรียกว่า Metaspace ซึ่งจะถูกเก็บไว้ในหน่วยความจำดั้งเดิม การอ้างอิง:http://www.programcreek.com/2013/04/jvm-run-time-data-areas/

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่


แผนภาพมีลักษณะอธิบายตนเองได้ดี ... นี่ใช้ได้สำหรับอัลกอริทึม GC ใด ๆ หรือไม่ G1 มีชุดที่แตกต่างกัน
Venkateswara Rao

@ Pythoner ฉันคิดว่าธงในสีม่วงเข้มควรเป็น-XX:PermSizeและไม่ใช่-XX:MaxPermSizeตามที่กำหนดไว้ข้างต้นแล้ว
Anurag

35

ด้วย Java8 พื้นที่ที่ไม่ใช่ฮีปจะไม่มี PermGen แต่ Metaspace ซึ่งเป็นการเปลี่ยนแปลงที่สำคัญใน Java8 ควรจะกำจัดข้อผิดพลาดหน่วยความจำออกด้วย Java เนื่องจากขนาด metaspace สามารถเพิ่มขึ้นได้ขึ้นอยู่กับพื้นที่ที่ jvm ต้องการสำหรับข้อมูลคลาส


1
ที่จริงแล้วมี metaspace และพื้นที่คลาส: docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ ......
mrswadge

23

หน่วยความจำ Java Heapเป็นส่วนหนึ่งของหน่วยความจำที่จัดสรรให้กับ JVM โดยระบบปฏิบัติการ

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

ป้อนคำอธิบายรูปภาพที่นี่

คุณสามารถค้นหารายละเอียดเพิ่มเติมเกี่ยวกับEden Space, Survivor Space, Tenured Space และ Permanent Generation ได้ในคำถามด้านล่าง:

รุ่นเยาว์อายุและการดัด

PermGen ถูกแทนที่ด้วย Metaspace ตั้งแต่ Java 8 รีลีส

เกี่ยวกับคำค้นหาของคุณ:

  1. Eden Space, Survivor Space, Tenured Space เป็นส่วนหนึ่งของหน่วยความจำกอง
  2. Metaspace และ Code Cache เป็นส่วนหนึ่งของหน่วยความจำที่ไม่ใช่ฮีป

Codecache: Java Virtual Machine (JVM) สร้างโค้ดเนทีฟและเก็บไว้ในพื้นที่หน่วยความจำที่เรียกว่า codecache JVM สร้างโค้ดเนทีฟด้วยเหตุผลหลายประการรวมถึงสำหรับ interpreter loop ที่สร้างขึ้นแบบไดนามิก, สเต็ป Java Native Interface (JNI) และสำหรับเมธอด Java ที่คอมไพล์เป็นโค้ดเนทีฟโดยคอมไพเลอร์ just-in-time (JIT) JIT นั้นเป็นผู้ใช้ codecache มากที่สุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.