วิธีการคงที่และตัวแปรคงที่เก็บไว้ใน Java อยู่ที่ไหน


116

ตัวอย่างเช่น:

class A {
    static int i=0;
    static int j;

   static void method() {
       // static k=0; can't use static for local variables only final is permitted
       // static int L;
    }
}

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


2
ลิงค์ที่มีประโยชน์มากในการทำความเข้าใจการรวบรวมขยะบนเว็บไซต์อย่างเป็นทางการของ Oracle: oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/…
Arnav Joshi

คำตอบ:


144

วิธีการคงที่ (ในความเป็นจริงทุกวิธี) รวมทั้งตัวแปรคงถูกเก็บไว้ในPermGenส่วนของฮีปเนื่องจากเป็นส่วนหนึ่งของข้อมูลการสะท้อน (ข้อมูลที่เกี่ยวข้องกับคลาสไม่เกี่ยวข้องกับอินสแตนซ์)

อัปเดตเพื่อชี้แจง :

โปรดทราบว่าเฉพาะตัวแปรและค่าทางเทคนิค (ดั้งเดิมหรือการอ้างอิง) เท่านั้นที่ถูกเก็บไว้ในพื้นที่ PermGen

หากตัวแปรคงที่ของคุณเป็นการอ้างอิงถึงอ็อบเจกต์ที่อ็อบเจ็กต์นั้นถูกเก็บไว้ในส่วนปกติของฮีป (คนรุ่นใหม่ / รุ่นเก่าหรือพื้นที่ผู้รอดชีวิต) อ็อบเจ็กต์เหล่านั้น (ยกเว้นว่าเป็นอ็อบเจ็กต์ภายในเช่นคลาส ฯลฯ ) จะไม่ถูกเก็บไว้ในพื้นที่ PermGen

ตัวอย่าง:

static int i = 1; //the value 1 is stored in the PermGen section
static Object o = new SomeObject(); //the reference(pointer/memory address) is stored in the PermGen section, the object itself is not.


คำเกี่ยวกับการเก็บขยะ:

ไม่ได้พึ่งพาfinalize()เป็นก็ไม่รับประกันว่าจะวิ่ง JVM ขึ้นอยู่กับ JVM ในการตัดสินใจว่าจะรันตัวเก็บขยะเมื่อใดและจะรวบรวมอะไรแม้ว่าอ็อบเจ็กต์จะมีสิทธิ์ได้รับการรวบรวมขยะก็ตาม

แน่นอนคุณสามารถตั้งค่าตัวแปรแบบคงที่เป็น null และลบการอ้างอิงไปยังอ็อบเจ็กต์บนฮีปได้ แต่นั่นไม่ได้หมายความว่าตัวรวบรวมขยะจะรวบรวมมัน (แม้ว่าจะไม่มีการอ้างอิงเพิ่มเติมก็ตาม)

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

หมายเหตุสุดท้าย : วิธีการจัดเก็บโค้ดข้อมูลรันไทม์ ฯลฯ ขึ้นอยู่กับ JVM ที่ใช้กล่าวคือ HotSpot อาจทำแตกต่างจาก JRockit และสิ่งนี้อาจแตกต่างกันไประหว่างเวอร์ชันของ JVM เดียวกัน ข้างต้นอ้างอิงจาก HotSpot สำหรับ Java 5 และ 6 (โดยพื้นฐานแล้วจะเหมือนกัน) ตั้งแต่ตอนที่ตอบฉันบอกว่าคนส่วนใหญ่ใช้ JVM เหล่านั้น เนื่องจากการเปลี่ยนแปลงที่สำคัญในโมเดลหน่วยความจำ ณ Java 8 ข้อความข้างต้นอาจไม่เป็นจริงสำหรับ Java 8 HotSpot - และฉันไม่ได้ตรวจสอบการเปลี่ยนแปลงของ Java 7 HotSpot ดังนั้นฉันเดาว่าข้างต้นยังคงเป็นจริงสำหรับเวอร์ชันนั้น แต่ฉันไม่แน่ใจที่นี่


1
คุณแน่ใจเกี่ยวกับตัวแปรคงที่? AFAIK PermGen เก็บเฉพาะคำจำกัดความที่ไม่ใช่ค่าที่แท้จริง
Amir Raminfar

2
@Amir ฉันค่อนข้างมั่นใจว่าตัวแปรนั้นถูกเก็บไว้ในพื้นที่ที่อนุญาตวัตถุที่อ้างอิงใด ๆ มักจะถูกจัดสรรบนฮีป สิ่งนี้อาจเพิ่มข้อมูลบางส่วน: stackoverflow.com/questions/3800444/…
โธมัส

1
อ่าใช่นิยามตัวแปรถูกเก็บไว้ใน permgen แต่ค่าจะอยู่ในฮีป คำตอบของคุณแนะนำว่าค่าจะถูกเก็บไว้ใน PermGen ด้วย
Amir Raminfar

1
@ แมทธิวคุณเข้าใจคำตอบของฉันได้อย่างไร? A กล่าวว่าตัวแปรถูกเก็บไว้ในส่วน permgen (primitives / references) ไม่ใช่ object ที่อ้างถึง ขึ้นอยู่กับว่าคุณดูค่าตัวแปรอย่างไร
โธมัส

1
@Nav ไม่ใช่ทุกส่วนของฮีปที่เก็บรวบรวมโดยค่าเริ่มต้นและบางครั้งคลาสจึงไม่สามารถรวบรวมตัวแปรแบบคงที่ได้เนื่องจากตัวโหลดคลาสยังคงมีการอ้างอิงอยู่ นอกจากนี้คุณไม่ควรพึ่งพาตัวรวบรวมขยะในการเรียกใช้เนื่องจากขึ้นอยู่กับ JVM โดยสิ้นเชิง (มันเป็นตัวกำหนดว่าจะเรียกใช้เมื่อใดและจะรวบรวมอะไรคุณสามารถระบุคำใบ้เช่น "ฉันต้องการให้คุณเรียกใช้ gc เดี๋ยวนี้" :)) .
โธมัส

25

ตัวแปรคลาส (ตัวแปรคงที่) จะถูกเก็บไว้เป็นส่วนหนึ่งของที่Class objectเกี่ยวข้องกับคลาสนั้น วัตถุคลาสนี้สามารถสร้างได้โดย JVM เท่านั้นและถูกเก็บไว้ในpermanent generationไฟล์.

ยังมีบางคนตอบว่าเก็บไว้ในพื้นที่ที่ไม่ใช่ heap ซึ่งเรียกว่าMethod Area.Even คำตอบนี้ก็ไม่ผิด เป็นเพียงหัวข้อที่ถกเถียงกันว่า Permgen Area เป็นส่วนหนึ่งของฮีปหรือไม่ เห็นได้ชัดว่าการรับรู้แตกต่างกันไปในแต่ละบุคคล ในความคิดของฉันเราให้พื้นที่ฮีปและพื้นที่อนุญาตแตกต่างกันในอาร์กิวเมนต์ JVM ดังนั้นจึงเป็นข้อสันนิษฐานที่ดีในการปฏิบัติต่อพวกเขาแตกต่างกัน

อีกวิธีหนึ่งในการดู

พูลหน่วยความจำถูกสร้างโดยตัวจัดการหน่วยความจำ JVM ระหว่างรันไทม์ พูลหน่วยความจำอาจเป็นของหน่วยความจำฮีปหรือไม่ใช่ฮีปพูลค่าคงที่ของเวลาทำงานคือการแสดงเวลารันต่อคลาสหรือต่ออินเทอร์เฟซของตาราง constant_pool ในไฟล์คลาส พูลค่าคงที่รันไทม์แต่ละตัวถูกจัดสรรจากพื้นที่วิธีการของเครื่องเสมือน Java และตัวแปรคงที่จะถูกเก็บไว้ในพื้นที่วิธีการนี้ นอกจากนี้ที่ไม่ใช่ฮีปนี้ก็ไม่มีอะไรนอกจากพื้นที่ perm gen จริงๆแล้วพื้นที่ Method เป็นส่วนหนึ่งของ perm gen ( อ้างอิง )

ใส่คำอธิบายภาพที่นี่


พื้นที่วิธีการไม่ใช่ส่วนย่อยของส่วน PermGen ของหน่วยความจำหรือไม่? เหตุใดคุณจึงแสดงพื้นที่วิธีการเป็นส่วนหนึ่งของหน่วยความจำที่ไม่ใช่ฮีปในเมื่อฉันคิดว่าพวกเขา (PermGen พร้อมกับพื้นที่วิธีการ (คลาส)) เป็นส่วนหนึ่งของพื้นที่ฮีปที่ใหญ่กว่าของ JVM
Kaveesh Kanwal

อ่านบรรทัดสุดท้าย -Also this non-heap is nothing but perm gen area.Actually Method area is part of perm gen.
Aniket Thakur

1
@AniketThakur คุณได้แสดงพื้นที่วิธีการเป็นส่วนหนึ่งของหน่วยความจำที่ไม่ใช่ฮีป แต่ตามเอกสารของ oracle ที่นี่docs.oracle.com/javase/specs/jvms/se7/html/…มีการกล่าวถึงพื้นที่วิธีการเป็นส่วนหนึ่งของเหตุผล กอง
Karan

21

ก่อน Java 8:

ตัวแปรคงที่ถูกเก็บไว้ในพื้นที่ Permgen (เรียกอีกอย่างว่าพื้นที่วิธีการ)

PermGen Space เป็นที่รู้จักกันในชื่อ Method Area

PermGen Space ใช้เก็บสิ่งของ 3 อย่าง

  1. ข้อมูลระดับชั้นเรียน (meta-data)
  2. สตริงภายใน
  3. ตัวแปรคงที่

ตั้งแต่ Java 8 เป็นต้นไป

ตัวแปรคงที่จะถูกเก็บไว้ใน Heap เองตั้งแต่ Java 8 เป็นต้นไป PermGen Space จะถูกลบออกและมีการนำ Space ใหม่ที่ชื่อ MetaSpace มาใช้ซึ่งไม่ใช่ส่วนของ Heap อีกต่อไปซึ่งแตกต่างจาก Permgen Space ก่อนหน้านี้ Meta-Space มีอยู่ในหน่วยความจำเนทีฟ (หน่วยความจำที่ OS จัดเตรียมให้กับแอปพลิเคชันเฉพาะสำหรับการใช้งานของมันเอง) และตอนนี้จะจัดเก็บเฉพาะข้อมูลเมตาคลาสเท่านั้น

สตริงภายในและตัวแปรสแตติกจะถูกย้ายไปยังฮีปเอง

ดูข้อมูลอย่างเป็นทางการ: JEP 122: ลบ Permanent Gen Space


เมื่อคุณพูดว่า "heap เอง" สำหรับตัวแปรคงที่> Java8 โดยที่: OldGen?
Ewoks

15

นี่คือคำถามที่มีคำตอบง่ายๆและคำตอบที่ยืดยาว

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

คำตอบแบบยาวมีอยู่แล้วใน stack overflow:

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


3
แน่นอน! อย่าลืมโหวตคนเหล่านั้นถ้าคุณคิดว่าพวกเขามีประโยชน์
Vasiliy Sharapov


5

นอกจากคำตอบของ Thomas แล้วตัวแปรแบบคงที่จะถูกเก็บไว้ในพื้นที่ที่ไม่ใช่ฮีปซึ่งเรียกว่า Method Area


4

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


3

ตัวแปรคงถูกเก็บไว้ในฮีป


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