Stack Memory และ Heap Space ใน Java

1. บทนำ

ในการเรียกใช้แอปพลิเคชันด้วยวิธีที่เหมาะสมที่สุด JVM จะแบ่งหน่วยความจำออกเป็นหน่วยความจำแบบสแต็กและฮีป เมื่อใดก็ตามที่เราประกาศตัวแปรและออบเจ็กต์ใหม่ให้เรียกใช้เมธอดใหม่ประกาศStringหรือดำเนินการที่คล้ายกัน JVM จะกำหนดหน่วยความจำให้กับการดำเนินการเหล่านี้จาก Stack Memory หรือ Heap Space

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

2. Stack Memory ใน Java

Stack Memory ใน Java ใช้สำหรับการจัดสรรหน่วยความจำแบบคงที่และการดำเนินการของเธรด ประกอบด้วยค่าดั้งเดิมที่เฉพาะเจาะจงสำหรับวิธีการและการอ้างอิงถึงอ็อบเจ็กต์ที่อยู่ในฮีปซึ่งอ้างถึงจากเมธอด

การเข้าถึงหน่วยความจำนี้อยู่ในลำดับ Last-In-First-Out (LIFO) เมื่อใดก็ตามที่มีการเรียกใช้เมธอดใหม่บล็อกใหม่ที่ด้านบนของสแต็กจะถูกสร้างขึ้นซึ่งมีค่าเฉพาะสำหรับเมธอดนั้นเช่นตัวแปรดั้งเดิมและการอ้างอิงถึงอ็อบเจ็กต์

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

2.1. คุณสมบัติที่สำคัญของหน่วยความจำแบบกองซ้อน

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

  • มันจะเติบโตและหดตัวเมื่อมีการเรียกวิธีการใหม่และส่งคืนตามลำดับ
  • ตัวแปรภายในสแต็กจะมีอยู่ตราบเท่าที่เมธอดที่สร้างขึ้นนั้นทำงานอยู่
  • จะจัดสรรและยกเลิกการจัดสรรโดยอัตโนมัติเมื่อวิธีการเสร็จสิ้นการดำเนินการ
  • หากหน่วยความจำนี้เต็ม Java จะพ่นjava.lang.StackOverFlowError
  • การเข้าถึงหน่วยความจำนี้ทำได้รวดเร็วเมื่อเทียบกับหน่วยความจำฮีป
  • หน่วยความจำนี้ปลอดภัยต่อเธรดเนื่องจากแต่ละเธรดทำงานในสแตกของตัวเอง

3. Heap Space ใน Java

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

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

โมเดลหน่วยความจำนี้ถูกแบ่งออกเป็นส่วนย่อย ๆ ที่เรียกว่าชั่วอายุคนซึ่ง ได้แก่ :

  1. Young Generation -นี่คือที่ที่วัตถุใหม่ทั้งหมดได้รับการจัดสรรและอายุ การรวบรวมขยะเล็กน้อยเกิดขึ้นเมื่อสิ่งนี้เต็มไป
  2. Old หรือ Tenured Generation -นี่คือที่เก็บวัตถุที่มีอายุยืนยาว เมื่อวัตถุถูกเก็บไว้ใน Young Generation จะมีการกำหนดเกณฑ์สำหรับอายุของวัตถุและเมื่อถึงเกณฑ์นั้นวัตถุจะถูกย้ายไปยังรุ่นเก่า
  3. การสร้างแบบถาวร -ประกอบด้วยข้อมูลเมตาของ JVM สำหรับคลาสรันไทม์และวิธีการสมัคร

ส่วนต่างๆเหล่านี้จะกล่าวถึงในบทความนี้ด้วย - ความแตกต่างระหว่าง JVM, JRE และ JDK

เราสามารถปรับเปลี่ยนขนาดของหน่วยความจำฮีปได้เสมอตามความต้องการของเรา สำหรับข้อมูลเพิ่มเติมโปรดไปที่บทความ Baeldung ที่เชื่อมโยงนี้

3.1. คุณสมบัติที่สำคัญของ Java Heap Memory

นอกเหนือจากสิ่งที่เราได้พูดถึงไปแล้วคุณสมบัติอื่น ๆ ของ heap space มีดังต่อไปนี้:

  • เข้าถึงได้โดยใช้เทคนิคการจัดการหน่วยความจำที่ซับซ้อนซึ่งรวมถึง Young Generation, Old หรือ Tenured Generation และ Permanent Generation
  • หากพื้นที่ฮีปเต็ม Java จะพ่นjava.lang.OutOfMemoryError
  • การเข้าถึงหน่วยความจำนี้ค่อนข้างช้ากว่าหน่วยความจำแบบสแต็ก
  • หน่วยความจำนี้ตรงกันข้ามกับสแต็กจะไม่ถูกจัดสรรโดยอัตโนมัติ จำเป็นต้องใช้ Garbage Collector เพื่อเพิ่มวัตถุที่ไม่ได้ใช้เพื่อรักษาประสิทธิภาพของการใช้งานหน่วยความจำ
  • ซึ่งแตกต่างจากสแต็กคือฮีปไม่ใช่เธรดที่ปลอดภัยและจำเป็นต้องได้รับการปกป้องโดยการซิงโครไนซ์โค้ดอย่างถูกต้อง

4. ตัวอย่าง

จากสิ่งที่เราได้เรียนรู้ไปแล้วเรามาวิเคราะห์โค้ด Java แบบง่าย ๆ และประเมินวิธีจัดการหน่วยความจำที่นี่:

class Person { int id; String name; public Person(int id, String name) { this.id = id; this.name = name; } } public class PersonBuilder { private static Person buildPerson(int id, String name) { return new Person(id, name); } public static void main(String[] args) { int id = 23; String name = "John"; Person person = null; person = buildPerson(id, name); } }

มาวิเคราะห์ทีละขั้นตอน:

  1. เมื่อเข้าสู่เมธอดmain ()ช่องว่างในหน่วยความจำสแต็กจะถูกสร้างขึ้นเพื่อจัดเก็บข้อมูลพื้นฐานและการอ้างอิงของวิธีนี้
    • ค่าดั้งเดิมของรหัสจำนวนเต็มจะถูกเก็บไว้ในหน่วยความจำสแตกโดยตรง
    • บุคคลที่เป็นตัวแปรอ้างอิงประเภทบุคคลจะถูกสร้างขึ้นในหน่วยความจำสแต็กซึ่งจะชี้ไปที่วัตถุจริงในฮีป
  2. การเรียกใช้ตัวสร้างพารามิเตอร์Person (int, String)จากmain ()จะจัดสรรหน่วยความจำเพิ่มเติมที่ด้านบนของสแต็กก่อนหน้า สิ่งนี้จะจัดเก็บ:
    • การอ้างอิงอ็อบเจ็กต์นี้ของอ็อบเจ็กต์การเรียกในหน่วยความจำสแตก
    • รหัสค่าดั้งเดิมในหน่วยความจำสแต็ก
    • ตัวแปรอ้างอิงของชื่ออาร์กิวเมนต์Stringซึ่งจะชี้ไปยังสตริงจริงจากสตริงพูลในหน่วยความจำฮีป
  3. หลักวิธีการที่เพิ่มเติมโทรbuildPerson ()วิธีการแบบคงที่จัดสรรต่อไปจะเกิดขึ้นในหน่วยความจำสแต็คที่ด้านบนของหนึ่งก่อนหน้านี้ สิ่งนี้จะจัดเก็บตัวแปรในลักษณะที่อธิบายไว้ข้างต้นอีกครั้ง
  4. อย่างไรก็ตามสำหรับวัตถุที่สร้างขึ้นใหม่คนประเภทบุคคล , เช่นตัวแปรทั้งหมดจะถูกเก็บไว้ในหน่วยความจำกอง

การจัดสรรนี้อธิบายไว้ในแผนภาพนี้:

5. สรุป

ก่อนที่เราจะสรุปบทความนี้เรามาสรุปความแตกต่างระหว่าง Stack Memory และ Heap Space อย่างรวดเร็ว:

พารามิเตอร์ หน่วยความจำกอง พื้นที่กอง
ใบสมัคร Stack is used in parts, one at a time during execution of a thread The entire application uses Heap space during runtime
Size Stack has size limits depending upon OS and is usually smaller then Heap There is no size limit on Heap
Storage Stores only primitive variables and references to objects that are created in Heap Space All the newly created objects are stored here
Order It is accessed using Last-in First-out (LIFO) memory allocation system This memory is accessed via complex memory management techniques that include Young Generation, Old or Tenured Generation, and Permanent Generation.
Life Stack memory only exists as long as the current method is running Heap space exists as long as the application runs
Efficiency Comparatively much faster to allocate when compared to heap Slower to allocate when compared to stack
Allocation/Deallocation หน่วยความจำนี้จะถูกจัดสรรและยกเลิกการจัดสรรโดยอัตโนมัติเมื่อมีการเรียกและส่งคืนเมธอดตามลำดับ พื้นที่ฮีปจะถูกจัดสรรเมื่อวัตถุใหม่ถูกสร้างและยกเลิกการจัดสรรโดย Gargabe Collector เมื่อไม่ได้อ้างอิงอีกต่อไป

6. บทสรุป

กองซ้อนและฮีปเป็นสองวิธีที่ Java จัดสรรหน่วยความจำ ในบทความนี้เราเข้าใจวิธีการทำงานและเวลาที่ควรใช้เพื่อพัฒนาโปรแกรม Java ที่ดีขึ้น

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการจัดการหน่วยความจำใน Java โปรดอ่านบทความนี้ที่นี่ นอกจากนี้เรายังได้กล่าวถึง JVM Garbage Collector ซึ่งจะกล่าวถึงโดยย่อในบทความนี้