คุณสมบัติที่สำคัญของ Java คือการจัดการการรีไซเคิลหน่วยความจำโดยอัตโนมัติผ่าน Garbage Collector (GC) โดยไม่ต้องใช้โปรแกรมเมอร์เพื่อเพิ่มหน่วยความจำด้วยตนเอง ในทางทฤษฎีหน่วยความจำทั้งหมดที่ถูกครอบครองโดยวัตถุที่จะไม่ถูกใช้ใน Java อีกต่อไปสามารถนำกลับมาใช้ใหม่ได้โดย GC แต่ Java ก็มีการรั่วไหลของหน่วยความจำ แต่ประสิทธิภาพของมันแตกต่างจาก C ++
การจัดการหน่วยความจำใน Java
เพื่อให้เข้าใจการรั่วไหลของหน่วยความจำใน Java คุณต้องรู้ก่อนว่าหน่วยความจำใน Java มีการจัดการอย่างไร
ในโปรแกรม Java เรามักจะใช้ใหม่เพื่อจัดสรรหน่วยความจำให้กับวัตถุและพื้นที่หน่วยความจำเหล่านี้อยู่บนกอง (heap)
นี่คือตัวอย่าง:
คลาสสาธารณะง่าย {โมฆะคงที่สาธารณะหลัก (สตริง args []) {วัตถุวัตถุ 1 = วัตถุใหม่ (); // obj1 object Object2 = วัตถุใหม่ (); // obj2 Object2 = Object1; //... ในเวลานี้ OBJ2 สามารถทำความสะอาดได้}}Java ใช้กราฟโดยตรงสำหรับการจัดการหน่วยความจำ:
ในกราฟกำกับเราเรียกว่า OBJ1 สามารถเข้าถึงได้ OBJ2 ว่าไม่สามารถเข้าถึงได้และไม่สามารถเข้าถึงได้อย่างเห็นได้ชัด
การเปิดตัวหน่วยความจำนั่นคือการทำความสะอาดวัตถุที่ไม่สามารถเข้าถึงได้ถูกกำหนดและดำเนินการโดย GC ดังนั้น GC จะตรวจสอบสถานะของแต่ละวัตถุรวมถึงแอปพลิเคชันการอ้างอิงการอ้างอิงและการมอบหมาย หลักการพื้นฐานของการปล่อยวัตถุคือวัตถุจะไม่ถูกใช้อีกต่อไป:
วัตถุได้รับค่า NULL และไม่เคยถูกเรียกอีกครั้ง
อื่น ๆ คือการกำหนดค่าใหม่ให้กับวัตถุซึ่งจัดสรรพื้นที่หน่วยความจำใหม่
โดยปกติแล้วจะเชื่อว่าค่าใช้จ่ายในการจัดสรรวัตถุบนกองค่อนข้างสูง แต่ GC ปรับการดำเนินการนี้ให้เหมาะสม: ใน C ++ การจัดสรรหน่วยความจำบนกองจะมองหาหน่วยความจำที่เหมาะสมเพื่อจัดสรร หากวัตถุถูกทำลายหน่วยความจำชิ้นนี้สามารถนำกลับมาใช้ใหม่ได้ ใน Java คุณต้องการแถบยาว ทุกครั้งที่มีการจัดสรรวัตถุใหม่ "heap pointer" ของ Java จะเคลื่อนที่ย้อนหลังไปยังพื้นที่ที่ไม่ได้รับการจัดสรร ดังนั้นประสิทธิภาพของหน่วยความจำที่จัดสรร Java จึงเปรียบได้กับของ C ++
แต่มีปัญหาเกี่ยวกับวิธีการทำงานนี้: หากมีการใช้หน่วยความจำบ่อยครั้งทรัพยากรจะหมดลง ในเวลานี้ GC เข้ามาแทรกแซงพื้นที่และทำให้วัตถุในกองกะทัดรัดมากขึ้น ด้วยวิธีนี้จะมีพื้นที่หน่วยความจำเพียงพอที่จะจัดสรร
วิธีการนับอ้างอิงเมื่อการทำความสะอาด GC: เมื่อการอ้างอิงเชื่อมต่อกับวัตถุใหม่จำนวนการอ้างอิงคือ +1; เมื่อการอ้างอิงออกจากขอบเขตหรือตั้งค่าเป็นโมฆะจำนวนการอ้างอิงคือ -1 เมื่อ GC พบว่าการนับนี้คือ 0 มันจะรีไซเคิลหน่วยความจำที่ใช้ ค่าใช้จ่ายนี้เกิดขึ้นตลอดอายุการใช้งานของโปรแกรมอ้างอิงและไม่สามารถจัดการกับการอ้างอิงแบบวงกลมได้ ดังนั้นวิธีนี้ใช้เพื่อแสดงให้เห็นว่า GC ทำงานอย่างไรและจะไม่ถูกนำไปใช้โดยเครื่องเสมือน Java ใด ๆ
GCs ส่วนใหญ่ใช้วิธีการทำความสะอาดแบบปรับตัว (รวมถึงเทคนิคเพิ่มเติมอื่น ๆ สำหรับการเพิ่มความเร็ว) ส่วนใหญ่ขึ้นอยู่กับการค้นหาวัตถุ "สด" ใด ๆ จากนั้นใช้ "ตัวปรับแต่งแบบปรับตัว, หยุดการทำเครื่องหมาย" ทำความสะอาด " ฉันจะไม่แนะนำมากเกินไปนี่ไม่ใช่จุดสนใจของบทความนี้
หน่วยความจำรั่วในชวา
การรั่วไหลของหน่วยความจำใน Java ในวงกว้างและในแง่ของ Layman คือหน่วยความจำของวัตถุที่ไม่สามารถใช้งานได้อีกต่อไปไม่สามารถรีไซเคิลได้ซึ่งเป็นการรั่วไหลของหน่วยความจำ
การรั่วไหลของหน่วยความจำใน Java นั้นแตกต่างจากใน C ++
ใน C ++ วัตถุทั้งหมดที่ได้รับการจัดสรรหน่วยความจำจะต้องได้รับการปล่อยตัวโดยโปรแกรมเมอร์ด้วยตนเองหลังจากที่พวกเขาไม่ได้ใช้อีกต่อไป ดังนั้นแต่ละชั้นเรียนจะมี destructor ซึ่งก็คือการทำความสะอาดให้เสร็จสมบูรณ์ หากเราลืมปล่อยวัตถุบางอย่างมันจะทำให้หน่วยความจำรั่วไหล
แต่ใน Java เราไม่จำเป็นต้อง (และไม่สามารถ) ปลดปล่อยความทรงจำได้ด้วยตัวเองและวัตถุที่ไร้ประโยชน์จะถูกทำความสะอาดโดยอัตโนมัติโดย GC ซึ่งทำให้งานการเขียนโปรแกรมของเราง่ายขึ้นอย่างมาก อย่างไรก็ตามบางครั้งวัตถุบางอย่างที่ไม่สามารถใช้งานได้อีกต่อไปไม่สามารถปล่อยใน GC ซึ่งจะทำให้เกิดการรั่วไหลของหน่วยความจำ
เรารู้ว่าวัตถุมีวัฏจักรชีวิตบางอย่างยาวและบางส่วนสั้น หากวัตถุวัฏจักรชีวิตที่ยาวนานมีการอ้างอิงด้วยวงจรชีวิตระยะสั้นการรั่วไหลของหน่วยความจำน่าจะเป็น ยกตัวอย่างง่ายๆ:
คลาสสาธารณะง่าย ๆ {วัตถุวัตถุ; โมฆะสาธารณะวิธีการ 1 () {object = new Object (); //....Hother Code}}ในความเป็นจริงเราคาดหวังว่ามันจะถูกใช้ในวิธี Method1 () เท่านั้นและจะไม่ถูกใช้ที่อื่น อย่างไรก็ตามเมื่อวิธีการ Method1 () ถูกเรียกใช้งานหน่วยความจำที่จัดสรรโดยวัตถุวัตถุจะไม่ถูกพิจารณาทันทีว่าเป็นวัตถุที่สามารถปล่อยออกมาและจะถูกปล่อยออกมาหลังจากวัตถุที่สร้างโดยคลาส Simple จะถูกปล่อยออกมา พูดอย่างเคร่งครัดนี่คือการรั่วไหลของหน่วยความจำ วิธีแก้ปัญหาคือการใช้วัตถุเป็นตัวแปรท้องถิ่นในวิธี Method1 () แน่นอนถ้าคุณต้องเขียนสิ่งนี้คุณสามารถเปลี่ยนเป็นสิ่งนี้ได้:
คลาสสาธารณะง่าย ๆ {วัตถุวัตถุ; โมฆะสาธารณะวิธีการ 1 () {object = new Object (); //....Hother Code Object = NULL; -ด้วยวิธีนี้หน่วยความจำที่จัดสรรโดย "newobject ()" สามารถนำกลับมาใช้ใหม่ได้โดย GC
ณ จุดนี้การรั่วไหลของหน่วยความจำ Java ควรชัดเจนขึ้น มาอธิบายเพิ่มเติมด้านล่าง:
เมื่อหน่วยความจำที่จัดสรรในกองไม่ได้ถูกปล่อยออกมาทุกวิธีในการเข้าถึงหน่วยความจำนี้จะถูกลบ (เช่นการกำหนดตัวชี้ใหม่) นี่คือภาษาเช่น C ++ GC ใน Java จะช่วยเราจัดการกับสถานการณ์นี้ดังนั้นเราไม่จำเป็นต้องดูแล
เมื่อไม่จำเป็นต้องใช้วัตถุหน่วยความจำมันยังคงรักษาหน่วยความจำนี้และวิธีการเข้าถึง (การอ้างอิง) ซึ่งเป็นการรั่วไหลของหน่วยความจำที่อาจเกิดขึ้นในทุกภาษา หากคุณไม่ระวังเมื่อเขียนโปรแกรมสิ่งนี้จะเกิดขึ้นได้ง่ายและถ้ามันไม่ร้ายแรงเกินไปมันอาจจะเป็นเพียงการรั่วไหลของหน่วยความจำสั้น ๆ
ตัวอย่างและวิธีแก้ปัญหาที่มีแนวโน้มที่จะรั่วไหลของหน่วยความจำ
สถานการณ์เช่นตัวอย่างข้างต้นเป็นเรื่องง่ายที่จะเกิดขึ้นและเป็นสถานการณ์ที่เป็นไปได้มากที่สุดที่เราไม่สนใจและทำให้เกิดการรั่วไหลของหน่วยความจำ วิธีแก้ปัญหาคือการลดขอบเขตของวัตถุให้น้อยที่สุด (ตัวอย่างเช่นใน Androidstudio รหัสข้างต้นจะออกคำเตือนและคำแนะนำที่ให้คือการเขียนตัวแปรสมาชิกของคลาสเป็นตัวแปรท้องถิ่นในวิธีการ) และตั้งค่าโมฆะด้วยตนเอง
สำหรับขอบเขตเราต้องให้ความสนใจมากขึ้นเมื่อเขียนรหัส การตั้งค่าค่า NULL ด้วยตนเองเราสามารถดูวิธีการภายในของการลบโหนดที่ระบุในซอร์สโค้ด LinkedList Java คอนเทนเนอร์ (ดูที่: การตีความซอร์สโค้ด LinkedList ของ Java (JDK1.8) ):::
// ลบโหนดที่ระบุและส่งคืนค่าองค์ประกอบที่ถูกลบ e unlink (โหนด <e> x) {// รับค่าปัจจุบันและโหนดด้านหน้าและด้านหลัง Element E Element = X.Item; โหนดสุดท้าย <e> next = x.next; โหนดสุดท้าย <e> prev = x.prev; if (prev == null) {first = next; // ถ้าโหนดก่อนหน้านั้นว่างเปล่า (เช่นโหนดปัจจุบันเป็นโหนดแรก) โหนดถัดไปจะกลายเป็นโหนดแรก} อื่น {prev.next = next; // ถ้าโหนดก่อนหน้าไม่ว่างเปล่า } if (next == null) {last = prev; // ถ้าโหนดถัดไปว่างเปล่า (เช่นโหนดปัจจุบันเป็นโหนดหาง) หนึ่งในก่อนหน้าของโหนดปัจจุบันจะกลายเป็นโหนดหางใหม่} อื่น {next.prev = prev; // ถ้าโหนดถัดไปไม่ว่างเปล่าโหนดถัดไปจะไปข้างหน้าไปยังโหนดก่อนหน้า } x.item = null; ขนาด--; Modcount ++; องค์ประกอบกลับ; -นอกเหนือจากการปรับเปลี่ยนความสัมพันธ์ระหว่างโหนดสิ่งที่เราต้องทำคือการกำหนดค่าให้เป็นโมฆะ ไม่ว่า GC จะเริ่มทำความสะอาดเมื่อใดเราควรทำเครื่องหมายวัตถุที่ไร้ประโยชน์เป็นวัตถุที่ทำความสะอาดได้ทันเวลา
เรารู้ว่า arraylist คอนเทนเนอร์ Java ถูกนำไปใช้ในอาร์เรย์ (อ้างอิงถึง: การตีความซอร์สโค้ด arraylist ของ Java (JDK1.8) ) หากเราต้องการเขียนวิธี POP () (POP) สำหรับมันมันอาจมีลักษณะเช่นนี้:
สาธารณะ e pop () {ถ้า (ขนาด == 0) ส่งคืนค่า null; return (e) elementData [-ขนาด]; -วิธีการเขียนนั้นกระชับมาก แต่มันจะทำให้หน่วยความจำล้นที่นี่: ElementData [size-1] ยังคงมีการอ้างอิงถึงวัตถุประเภท e และไม่สามารถรีไซเคิลได้โดย GC ในขณะนี้ เราสามารถแก้ไขได้ดังนี้:
สาธารณะ e pop () {ถ้า (ขนาด == 0) ส่งคืนค่า null; อื่น {e e = (e) elementData [-ขนาด]; ElementData [ขนาด] = null; กลับ E; -เมื่อเขียนโค้ดเราไม่สามารถติดตามความเรียบง่ายได้อย่างสุ่มสี่สุ่มห้า สิ่งแรกคือเพื่อให้แน่ใจว่ามีความแม่นยำ
การรั่วไหลของหน่วยความจำระหว่างการใช้คอนเทนเนอร์
ในหลายบทความคุณอาจเห็นตัวอย่างของการรั่วไหลของหน่วยความจำดังนี้:
เวกเตอร์ v = เวกเตอร์ใหม่ (); สำหรับ (int i = 1; i <100; i ++) {object o = วัตถุใหม่ (); V.Add (O); o = null; -หลายคนอาจไม่เข้าใจในตอนแรกดังนั้นเราจึงสามารถเข้าใจรหัสข้างต้นดังนี้:
วิธีการโมฆะ () {เวกเตอร์เวกเตอร์ = เวกเตอร์ใหม่ (); สำหรับ (int i = 1; i <100; i ++) {Object Object = New Object (); vector.add (วัตถุ); วัตถุ = null; } //...Operations บนเวกเตอร์ // ... การดำเนินการอื่น ๆ ที่ไม่เกี่ยวข้องกับเวกเตอร์}ที่นี่การรั่วไหลของหน่วยความจำหมายถึงความจริงที่ว่าหลังจากการดำเนินการเวกเตอร์เสร็จสิ้นหากการดำเนินการ GC เกิดขึ้นวัตถุชุดนี้ไม่สามารถรีไซเคิลได้ การรั่วไหลของหน่วยความจำที่นี่อาจมีอายุสั้นเพราะหลังจากใช้วิธีทั้งหมด () วิธีการวัตถุเหล่านั้นยังสามารถรีไซเคิลได้ มันง่ายมากที่จะแก้ไขที่นี่เพียงกำหนดค่าด้วยตนเองให้เป็นโมฆะ:
วิธีการโมฆะ () {เวกเตอร์เวกเตอร์ = เวกเตอร์ใหม่ (); สำหรับ (int i = 1; i <100; i ++) {Object Object = New Object (); vector.add (วัตถุ); วัตถุ = null; } //...Operations บน V Vector = NULL; //... การดำเนินการอื่น ๆ ที่ไม่เกี่ยวข้องกับ v}เวกเตอร์ข้างต้นล้าสมัย แต่เป็นเพียงการแนะนำการรั่วไหลของหน่วยความจำโดยใช้ตัวอย่างเก่า เมื่อเราใช้ภาชนะมันเป็นเรื่องง่ายที่จะทำให้เกิดการรั่วไหลของหน่วยความจำเช่นเดียวกับตัวอย่างด้านบน อย่างไรก็ตามในตัวอย่างข้างต้นเอฟเฟกต์การรั่วไหลของหน่วยความจำที่เกิดจากตัวแปรท้องถิ่นในวิธีการในช่วงเวลาคอนเทนเนอร์อาจไม่ใหญ่มาก (แต่เราควรหลีกเลี่ยง) อย่างไรก็ตามหากคอนเทนเนอร์นี้เป็นตัวแปรสมาชิกของคลาสหรือแม้แต่ตัวแปรสมาชิกแบบคงที่คุณควรให้ความสนใจกับการรั่วไหลของหน่วยความจำมากขึ้น
ต่อไปนี้เป็นข้อผิดพลาดที่อาจเกิดขึ้นเมื่อใช้คอนเทนเนอร์:
การรวบรวมคลาสสาธารณะ {โมฆะสาธารณะคงที่หลัก (String s []) {set <MyObject> objects = ใหม่ linkedHashSet <myObject> (); Objects.add (ใหม่ myobject ()); Objects.add (ใหม่ myobject ()); Objects.add (ใหม่ myobject ()); Objects.add (ใหม่ myobject ()); System.out.println (Objects.size ()); ในขณะที่ (จริง) {objects.add (ใหม่ myobject ()); }}} คลาส MyObject {// ตั้งค่าความยาวอาร์เรย์เริ่มต้นเป็น 99999 และเกิดขึ้นเร็วกว่ารายการ outofMemoryError <String> รายการ = new ArrayList <> (99999);}การรันรหัสด้านบนจะรายงานข้อผิดพลาดอย่างรวดเร็ว:
3 exception ในด้าย "Main" Java.lang.outofMemoryError: พื้นที่ java heap ที่ java.util.arraylist. <init> (arraylist.java:152) ที่ com.anxpp.memory.myobject. com.anxpp.memory.CollectionMemory.Main (CollectionMemory.java:16)
หากคุณรู้เพียงพอเกี่ยวกับคอนเทนเนอร์ Java ข้อผิดพลาดข้างต้นจะไม่เกิดขึ้น นี่คือโพสต์ที่ฉันแนะนำคอนเทนเนอร์ Java: ...
คอนเทนเนอร์ตั้งค่าเฉพาะการจัดเก็บองค์ประกอบที่ไม่ซ้ำกันและเปรียบเทียบผ่านวิธี Equals () ของวัตถุ อย่างไรก็ตามคลาสทั้งหมดใน Java นั้นได้รับการสืบทอดโดยตรงหรือโดยอ้อมไปยังคลาส Object วิธี Equals () ของคลาสวัตถุเปรียบเทียบที่อยู่ของวัตถุ ในตัวอย่างข้างต้นองค์ประกอบจะถูกเพิ่มจนกว่าหน่วยความจำล้น
ดังนั้นตัวอย่างข้างต้นคือการพูดอย่างเคร่งครัดหน่วยความจำล้นที่เกิดจากการใช้งานที่ไม่ถูกต้องของคอนเทนเนอร์
เท่าที่เกี่ยวข้องกับการตั้งค่าวิธีการลบ () ยังใช้วิธี Equals () เพื่อลบองค์ประกอบการจับคู่ หากวัตถุมีวิธีการที่ถูกต้องเท่ากับ () โปรดจำไว้ว่าอย่าใช้ลบ (ObjectO) หลังจากแก้ไขวัตถุนี้สิ่งนี้อาจทำให้หน่วยความจำรั่วไหล
วัตถุต่าง ๆ ที่ให้วิธีการใกล้ ()
ตัวอย่างเช่นเมื่อใช้การเชื่อมต่อฐานข้อมูล (DataSourse.getConnection ()) การเชื่อมต่อเครือข่าย (ซ็อกเก็ต) และการเชื่อมต่อ IO และเมื่อใช้เฟรมเวิร์กอื่น ๆ พวกเขาจะไม่ได้รีไซเคิลโดย GC โดยอัตโนมัติ ในความเป็นจริงเหตุผลก็คือวัตถุวัฏจักรชีวิตที่ยาวนานมีการอ้างอิงถึงวัตถุวัฏจักรชีวิตระยะสั้น
หลายคนอาจใช้ไฮเบอร์เนต เมื่อเราใช้งานฐานข้อมูลเราจะได้รับเซสชันผ่าน SessionFactory:
เซสชัน = sessionfactory.opensession ();
หลังจากเสร็จสิ้นเราต้องเรียกวิธีปิด () เพื่อปิด:
session.close ();
SessionFactory เป็นวัตถุที่มีอายุการใช้งานยาวนานและเซสชันเป็นวัตถุที่ค่อนข้างสั้น แต่เฟรมเวิร์กได้รับการออกแบบด้วยวิธีนี้: มันไม่ทราบว่าเราจะใช้เซสชันนานแค่ไหนดังนั้นมันจึงสามารถให้วิธีการสำหรับเราในการตัดสินใจเมื่อเราจะไม่ใช้มันอีกต่อไป
เนื่องจากข้อยกเว้นอาจถูกโยนลงก่อนที่จะเรียกวิธีการปิด () ดังนั้นวิธีการไม่สามารถเรียกได้ เรามักจะใช้ภาษาลองแล้วในที่สุดก็ดำเนินการปิด () และงานทำความสะอาดอื่น ๆ ในคำสั่ง:
ลอง {session = sessionfactory.opensession (); //....Hother Operations} ในที่สุด {session.close (); -การรั่วไหลของหน่วยความจำที่เกิดจากโหมดซิงเกิลตัน
ในหลายกรณีเราสามารถพิจารณาวงจรชีวิตของมันคล้ายกับวงจรชีวิตของโปรแกรมทั้งหมดดังนั้นจึงเป็นวัตถุที่มีวงจรชีวิตที่ยาวนาน หากวัตถุนี้มีการอ้างอิงถึงวัตถุอื่น ๆ การรั่วไหลของหน่วยความจำก็มีแนวโน้มที่จะเกิดขึ้น
การอ้างอิงถึงคลาสภายในและโมดูลภายนอก
ในความเป็นจริงหลักการยังคงเหมือนเดิม แต่วิธีที่ปรากฏแตกต่างกัน
วิธีการที่เกี่ยวข้องกับการทำความสะอาด
ส่วนนี้ส่วนใหญ่พูดถึงวิธี GC () และสรุป () วิธีการ
GC ()
สำหรับโปรแกรมเมอร์ GC นั้นมีความโปร่งใสและมองไม่เห็น ฟังก์ชั่นที่เรียกใช้ GC คือ System.gc () และหลังจากเรียกมันแล้วมันจะเริ่มต้นเก็บขยะและเริ่มทำความสะอาด
อย่างไรก็ตามตามคำจำกัดความของข้อกำหนดภาษา Java ฟังก์ชั่นนี้ไม่รับประกันว่าตัวเก็บขยะของ JVM จะดำเนินการ เนื่องจากผู้ใช้ JVM ที่แตกต่างกันอาจใช้อัลกอริทึมที่แตกต่างกันเพื่อจัดการ GC โดยทั่วไปเธรดของ GC มีลำดับความสำคัญต่ำกว่า
มีกลยุทธ์มากมายสำหรับ JVM ที่จะโทรหา GC บางคนเริ่มทำงานเฉพาะเมื่อการใช้หน่วยความจำถึงระดับหนึ่ง บางคนดำเนินการเป็นประจำ บางคนดำเนินการ GC อย่างราบรื่นและบางคนดำเนินการ GC ในลักษณะที่ขัดจังหวะ แต่โดยทั่วไปแล้วเราไม่จำเป็นต้องสนใจเรื่องนี้ เว้นแต่ในบางสถานการณ์การดำเนินการของ GC มีผลต่อประสิทธิภาพของแอปพลิเคชัน ตัวอย่างเช่นสำหรับระบบบนเว็บแบบเรียลไทม์เช่นเกมออนไลน์ผู้ใช้ไม่ต้องการให้ GC ขัดจังหวะการดำเนินการของแอปพลิเคชันและดำเนินการรวบรวมขยะจากนั้นเราจำเป็นต้องปรับพารามิเตอร์ของ GC เพื่อให้ GC สามารถใช้หน่วยความจำได้อย่างราบรื่น HotSpotJVM จัดทำโดย Sun รองรับคุณสมบัตินี้
เสร็จสิ้น ()
Finalize () เป็นวิธีการในคลาสวัตถุ
ผู้ที่รู้ว่า C ++ รู้ว่ามี destructor แต่โปรดทราบว่าการสรุป () นั้นไม่ได้มีค่าเท่ากับ destructor ใน C ++
นี่คือการอธิบายในแนวคิดการเขียนโปรแกรม Java: เมื่อ GC พร้อมที่จะเพิ่มพื้นที่เก็บข้อมูลที่ครอบครองโดยวัตถุวิธีการสรุป () ของมันจะถูกเรียกก่อนและหน่วยความจำที่ถูกครอบครองโดยวัตถุจะถูกรีไซเคิลเฉพาะเมื่อการดำเนินการรีไซเคิล GC ครั้งต่อไปเกิดขึ้น
วัตถุประสงค์ที่สำคัญของวิธีนี้คือ: เมื่อเรียกรหัสที่ไม่ใช่ java (เช่น C และ C ++) ใน Java การดำเนินการหน่วยความจำที่สอดคล้องกัน (เช่นฟังก์ชัน malloc () ของ C) อาจใช้ในรหัสที่ไม่ใช่ Java เหล่านี้
ดังนั้นจึงสรุป () ไม่เหมาะสำหรับการทำความสะอาดทั่วไป
อย่างไรก็ตามบางครั้งวิธีนี้มีประโยชน์บางอย่าง:
หากมีชุดของวัตถุหนึ่งในวัตถุมีสถานะของเท็จ หากเราประมวลผลวัตถุนี้รัฐจะกลายเป็นจริง เพื่อหลีกเลี่ยงวัตถุที่หายไปโดยไม่ต้องประมวลผลคุณสามารถใช้วิธีการสรุป ():
คลาส myObject {boolean state = false; ข้อตกลงโมฆะสาธารณะ () {//... สถานะการดำเนินการประมวลผลบางอย่าง = true; } @Override void protected finalize () {if (! state) {system.out.println ("ข้อผิดพลาด:" + "วัตถุไม่ประมวลผล!"); -แต่จากหลาย ๆ ด้านวิธีนี้ไม่แนะนำให้ใช้และพิจารณาซ้ำซ้อน
โดยทั่วไปการรั่วไหลของหน่วยความจำเกิดจากการเข้ารหัสที่ไม่ดี เราไม่สามารถตำหนิ JVM ที่ไม่ทำความสะอาดได้อย่างสมเหตุสมผล
สรุป
ข้างต้นเป็นคำอธิบายโดยละเอียดทั้งหมดของรหัสหน่วยความจำที่รั่วไหลออกมาในภาษา Java ฉันหวังว่ามันจะเป็นประโยชน์กับทุกคน เพื่อนที่สนใจสามารถอ้างถึงหัวข้ออื่น ๆ ที่เกี่ยวข้องในเว็บไซต์นี้ต่อไป หากมีข้อบกพร่องใด ๆ โปรดฝากข้อความไว้เพื่อชี้ให้เห็น ขอบคุณเพื่อนที่ให้การสนับสนุนเว็บไซต์นี้!