การจัดการหน่วยความจำใน Java
หน่วยความจำสแต็คคืออะไร?
Stack ใน java เป็นส่วนหนึ่งของหน่วยความจำซึ่งประกอบด้วยวิธีการ ตัวแปรท้องถิ่น และตัวแปรอ้างอิง หน่วยความจำสแต็กจะถูกอ้างอิงตามลำดับเข้าก่อนออกก่อนเสมอ ตัวแปรท้องถิ่นจะถูกสร้างขึ้นในสแต็ก
หน่วยความจำฮีปคืออะไร?
ฮีปคือส่วนหนึ่งของหน่วยความจำซึ่งประกอบไปด้วยอ็อบเจ็กต์และอาจมีตัวแปรอ้างอิงด้วย ตัวแปรอินสแตนซ์จะถูกสร้างขึ้นในฮีป
การจัดสรรหน่วยความจำใน Java
การจัดสรรหน่วยความจำใน Java เป็นกระบวนการที่ส่วนของหน่วยความจำเสมือนถูกจัดเก็บไว้ในโปรแกรมสำหรับจัดเก็บตัวแปรและอินสแตนซ์ของโครงสร้างและคลาส อย่างไรก็ตาม หน่วยความจำไม่ได้ถูกจัดสรรให้กับออบเจ็กต์ในการประกาศ แต่จะมีการสร้างเฉพาะข้อมูลอ้างอิงเท่านั้น สำหรับการจัดสรรหน่วยความจำของออบเจ็กต์ จะใช้เมธอด new() ดังนั้นออบเจ็กต์จึงได้รับการจัดสรรหน่วยความจำบนฮีปเสมอ
การขอ Java การจัดสรรหน่วยความจำแบ่งออกเป็นส่วนต่างๆ ดังต่อไปนี้:
- กอง
- กอง
- รหัส
- คงที่
การแบ่งหน่วยความจำนี้จำเป็นสำหรับการจัดการที่มีประสิทธิภาพ
- การขอ รหัส ส่วนประกอบด้วยของคุณ รหัสไบต์.
- การขอ กอง ส่วนของหน่วยความจำประกอบด้วย วิธีการ ตัวแปรท้องถิ่น และตัวแปรอ้างอิง
- การขอ กอง ส่วนประกอบด้วย วัตถุ (อาจมีตัวแปรอ้างอิงด้วย)
- การขอ คงที่ ส่วนประกอบด้วย ข้อมูล/วิธีการแบบคงที่.
ความแตกต่างระหว่างตัวแปรท้องถิ่นและอินสแตนซ์
ตัวแปรอินสแตนซ์ มีการประกาศ ภายในชั้นเรียนแต่ไม่อยู่ในวิธีการ
class Student{ int num; // num is instance variable public void showData{}
ตัวแปรท้องถิ่น ถูกประกาศ ภายใน a วิธีการรวมทั้ง วิธี ข้อโต้แย้ง.
public void sum(int a){ int x = int a + 3; // a , x are local variables; }
ความแตกต่างระหว่างสแต็คและฮีป
คลิก Good Farm Animal Welfare Awards หากไม่สามารถเข้าถึงวิดีโอได้
มาดูตัวอย่างเพื่อให้เข้าใจเรื่องนี้ดีขึ้น ลองพิจารณาว่าเมธอดหลักของคุณที่เรียกใช้เมธอด m1
public void m1{ int x=20 }
ใน stack java เฟรมจะถูกสร้างขึ้นจากวิธี m1
ตัวแปร X ใน m1 จะถูกสร้างขึ้นในเฟรมสำหรับ m1 ในสแต็กด้วย (ดูภาพด้านล่าง)
วิธี m1 กำลังเรียกวิธี m2 ในสแต็กจาวา เฟรมใหม่จะถูกสร้างขึ้นสำหรับ m2 ที่ด้านบนของเฟรม m1
ตัวแปร b และ c จะถูกสร้างขึ้นในเฟรม m2 ในสแต็กด้วย
public void m2(int b){ boolean c; }
วิธีเดียวกันคือ m2 เรียกใช้เมธอด m3 อีกครั้ง เฟรม m3 จะถูกสร้างขึ้นที่ด้านบนสุดของสแต็ก (ดูภาพด้านล่าง)
ตอนนี้สมมติว่าเมธอด m3 ของเรากำลังสร้างออบเจ็กต์สำหรับคลาส "บัญชี" ซึ่งมีสองรายการ ตัวแปรอินสแตนซ์ int p และ int q
Account { Int p; Int q; }
นี่คือรหัสสำหรับวิธี m3
public void m3(){ Account ref = new Account(); // more code }
คำสั่ง new Account() จะสร้างออบเจ็กต์ของบัญชีในฮีป
ตัวแปรอ้างอิง “อ้างอิง” จะถูกสร้างขึ้นในสแต็กจาวา
ตัวดำเนินการกำหนดค่า “=” จะสร้างตัวแปรอ้างอิงเพื่อชี้ไปยังอ็อบเจ็กต์ในฮีป
เมื่อวิธีการดำเนินการเสร็จสิ้น กระแสการควบคุมจะย้อนกลับไปยังวิธีการที่เรียกใช้ ซึ่งในกรณีนี้คือวิธีการ m2
สแต็กจากวิธี m3 จะถูกล้างออก
เนื่องจากตัวแปรอ้างอิงจะไม่ชี้ไปที่ออบเจ็กต์ในฮีปอีกต่อไป จึงมีสิทธิ์สำหรับการรวบรวมขยะ
เมื่อวิธี m2 ดำเนินการเสร็จสิ้น วิธีดังกล่าวจะถูกนำออกจากสแต็ก และตัวแปรทั้งหมดจะถูกล้าง และจะไม่สามารถใช้งานได้อีกต่อไป
เช่นเดียวกันกับวิธี m1
ในที่สุด กระแสการควบคุมจะกลับสู่จุดเริ่มต้นของโปรแกรม ซึ่งโดยปกติแล้วจะเป็นวิธีการ "หลัก"
จะเกิดอะไรขึ้นถ้า Object มีการอ้างอิงเป็นตัวแปรอินสแตนซ์
public static void main(String args[]) { A parent = new A(); //more code } class A{ B child = new B(); int e; //more code } class B{ int c; int d; //more code }
ในกรณีนี้ ตัวแปรอ้างอิง "ลูก" จะถูกสร้างขึ้นในฮีป ซึ่งจะชี้ไปที่ออบเจ็กต์ของมัน คล้ายกับแผนภาพที่แสดงด้านล่าง
Garbage Collection อยู่ในอะไร Java?
เก็บขยะใน Java เป็นกระบวนการที่โปรแกรมดำเนินการจัดการหน่วยความจำโดยอัตโนมัติ Garbage Collector(GC) ค้นหาวัตถุที่ไม่ได้ใช้และลบออกเพื่อเรียกคืนหน่วยความจำ ใน Javaการจัดสรรหน่วยความจำแบบไดนามิกของวัตถุจะทำได้โดยใช้ตัวดำเนินการใหม่ซึ่งใช้หน่วยความจำบางส่วนและหน่วยความจำจะยังคงได้รับการจัดสรรจนกว่าจะมีการอ้างอิงสำหรับการใช้วัตถุนั้น
เมื่อไม่มีการอ้างอิงถึงวัตถุ จะถือว่าไม่จำเป็นอีกต่อไป และหน่วยความจำที่ครอบครองโดยวัตถุนั้นสามารถเรียกคืนได้ ไม่จำเป็นต้องทำลายวัตถุอย่างชัดเจน Java จัดการการยกเลิกการจัดสรรโดยอัตโนมัติ
เทคนิคที่ทำให้สิ่งนี้สำเร็จเรียกว่า เก็บขยะ- โปรแกรมที่ไม่ยกเลิกการจัดสรรหน่วยความจำอาจหยุดทำงานในที่สุดเมื่อไม่มีหน่วยความจำเหลืออยู่ในระบบที่จะจัดสรร โปรแกรมพวกนี้เค้าว่ากันว่ามี หน่วยความจำรั่ว เก็บขยะใน Java เกิดขึ้นโดยอัตโนมัติ ตลอดอายุการใช้งานของโปรแกรม ทำให้ไม่จำเป็นต้องยกเลิกการจัดสรรหน่วยความจำ และหลีกเลี่ยงการรั่วไหลของหน่วยความจำ
ในภาษา C เป็นความรับผิดชอบของโปรแกรมเมอร์ในการยกเลิกการจัดสรรหน่วยความจำที่จัดสรรแบบไดนามิกโดยใช้ฟังก์ชัน free() นี่คือที่ Java นำไปสู่การจัดการหน่วยความจำ
หมายเหตุ วัตถุทั้งหมดถูกสร้างขึ้นในส่วน Heap ของหน่วยความจำ รายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้อยู่ในบทช่วยสอนถัดไป
ตัวอย่าง: เรียนรู้กลไกการเก็บขยะใน Java
ขั้นตอน 1) คัดลอกโค้ดต่อไปนี้ลงในโปรแกรมแก้ไข
class Student{ int a; int b; public void setData(int c,int d){ a=c; b=d; } public void showData(){ System.out.println("Value of a = "+a); System.out.println("Value of b = "+b); } public static void main(String args[]){ Student s1 = new Student(); Student s2 = new Student(); s1.setData(1,2); s2.setData(3,4); s1.showData(); s2.showData(); //Student s3; //s3=s2; //s3.showData(); //s2=null; //s3.showData(); //s3=null; //s3.showData(); } }
ขั้นตอน 2) บันทึก คอมไพล์ และรันโค้ด ดังที่แสดงในแผนภาพ จะมีการสร้างออบเจ็กต์สองตัวและตัวแปรอ้างอิงสองตัว
ขั้นตอน 3) ไม่แสดงความคิดเห็นบรรทัดที่ 20,21,22 บันทึก คอมไพล์ และรันโค้ด
ขั้นตอน 4) ดังที่แสดงในแผนภาพด้านล่าง ตัวแปรอ้างอิงสองตัวกำลังชี้ไปที่วัตถุเดียวกัน
ขั้นตอน 5) บรรทัดที่ไม่ใส่เครื่องหมายข้อคิดเห็น # 23 และ 24 คอมไพล์ บันทึก และรันโค้ด
ขั้นตอน 6) ดังที่แสดงในแผนภาพด้านล่าง s2 กลายเป็นโมฆะ แต่ s3 ยังคงชี้ไปที่อ็อบเจ็กต์ และไม่มีสิทธิ์สำหรับการรวบรวมขยะ Java
ขั้นตอน 7) บรรทัดที่ไม่ใส่เครื่องหมายข้อคิดเห็น # 25 และ 26 บันทึก คอมไพล์ และรันโค้ด
ขั้นตอน 8) ณ จุดนี้ ไม่มีการอ้างอิงที่ชี้ไปที่ออบเจ็กต์ และมีสิทธิ์สำหรับการรวบรวมขยะ มันจะถูกลบออกจากหน่วยความจำ และไม่มีทางที่จะเรียกคืนมันกลับมาได้
วิธีการลบวัตถุใน Java?
1) หากคุณต้องการทำให้ออบเจ็กต์ของคุณมีสิทธิ์สำหรับ Garbage Collection ให้กำหนดตัวแปรอ้างอิงเป็น null
2) ประเภทดั้งเดิมไม่ใช่วัตถุ ไม่สามารถกำหนดให้เป็นโมฆะได้
สรุป:
- เมื่อเรียกใช้เมธอด เฟรมจะถูกสร้างขึ้นที่ด้านบนของสแต็ก
- เมื่อเมธอดดำเนินการเสร็จสิ้นแล้ว โฟลว์ของการควบคุมจะกลับไปยังเมธอดการเรียกและเฟรมสแต็กที่เกี่ยวข้องจะถูกล้าง
- ตัวแปรท้องถิ่นจะถูกสร้างขึ้นในสแต็ก
- ตัวแปรอินสแตนซ์ถูกสร้างขึ้นในฮีปและเป็นส่วนหนึ่งของออบเจ็กต์ที่ตัวแปรเหล่านั้นอยู่
- ตัวแปรอ้างอิงถูกสร้างขึ้นในสแต็ก