มีวิธีการเพิ่มหน่วยความจำใน Java คล้ายกับfree()
ฟังก์ชั่นของ C หรือไม่? หรือการตั้งค่าวัตถุให้เป็นโมฆะและอาศัย GC เป็นตัวเลือกเท่านั้น?
มีวิธีการเพิ่มหน่วยความจำใน Java คล้ายกับfree()
ฟังก์ชั่นของ C หรือไม่? หรือการตั้งค่าวัตถุให้เป็นโมฆะและอาศัย GC เป็นตัวเลือกเท่านั้น?
คำตอบ:
Java ใช้หน่วยความจำที่มีการจัดการดังนั้นวิธีเดียวที่คุณสามารถจัดสรรหน่วยความจำได้คือโดยใช้new
โอเปอเรเตอร์และวิธีเดียวที่คุณสามารถจัดสรรหน่วยความจำได้ก็คืออาศัยตัวรวบรวมขยะ
นี้จัดการหน่วยความจำเอกสาร (PDF) อาจช่วยอธิบายสิ่งที่เกิดขึ้น
นอกจากนี้คุณยังสามารถโทรติดต่อSystem.gc()
เพื่อแนะนำว่าตัวรวบรวมขยะทำงานได้ทันที อย่างไรก็ตาม Java Runtime ตัดสินใจขั้นสุดท้ายไม่ใช่รหัสของคุณ
อ้างอิงถึงเอกสาร Java ,
การเรียกใช้เมธอด gc แสดงให้เห็นว่า Java Virtual Machine ใช้ความพยายามในการรีไซเคิลวัตถุที่ไม่ได้ใช้เพื่อให้หน่วยความจำที่พวกเขาใช้อยู่ในปัจจุบันสามารถนำมาใช้ซ้ำได้อย่างรวดเร็ว เมื่อการควบคุมส่งคืนจากการเรียกใช้เมธอด Java Virtual Machine พยายามอย่างเต็มที่ในการเรียกคืนพื้นที่จากวัตถุที่ถูกทิ้งทั้งหมด
System.gc()
อย่างสิ้นเชิง
ดูเหมือนว่าไม่มีใครพูดถึงการตั้งค่าการอ้างอิงวัตถุอย่างชัดเจนnull
ซึ่งเป็นเทคนิคที่ถูกต้องตามกฎหมายในการ "เพิ่ม" หน่วยความจำที่คุณอาจต้องการพิจารณา
ตัวอย่างเช่นสมมติว่าคุณประกาศวิธีList<String>
เริ่มต้นของวิธีการที่ขยายขนาดให้ใหญ่มาก แต่จำเป็นต้องใช้จนถึงวิธีครึ่งทาง ณ จุดนี้คุณสามารถตั้งค่าการอ้างอิงรายการเป็นnull
เพื่ออนุญาตให้ตัวรวบรวมขยะสามารถเรียกคืนออบเจ็กต์นี้ได้ก่อนที่วิธีการจะเสร็จสิ้น
โปรดทราบว่าฉันไม่ค่อยได้ใช้เทคนิคนี้ในความเป็นจริง แต่มันก็คุ้มค่าที่จะพิจารณาเมื่อจัดการกับโครงสร้างข้อมูลที่มีขนาดใหญ่มาก
System.gc();
รันตัวรวบรวมขยะ
การเรียกใช้เมธอด gc แสดงให้เห็นว่า Java Virtual Machine ใช้ความพยายามในการรีไซเคิลวัตถุที่ไม่ได้ใช้เพื่อให้หน่วยความจำที่พวกเขาใช้อยู่ในปัจจุบันสามารถนำมาใช้ซ้ำได้อย่างรวดเร็ว เมื่อการควบคุมส่งคืนจากการเรียกใช้เมธอด Java Virtual Machine พยายามอย่างเต็มที่ในการเรียกคืนพื้นที่จากวัตถุที่ถูกทิ้งทั้งหมด
ไม่แนะนำ.
แก้ไข: ฉันเขียนคำตอบดั้งเดิมในปี 2009 ตอนนี้เป็นปี 2558
นักสะสมขยะได้ดีขึ้นเรื่อย ๆ ในรอบ 20 ปีของ Java ณ จุดนี้หากคุณโทรหาผู้รวบรวมขยะด้วยตนเองคุณอาจต้องพิจารณาแนวทางอื่น ๆ :
* "ฉันใช้ตัวแปร nulling เป็นตัวยึดตำแหน่งสำหรับการลบที่เหมาะสมในอนาคตตัวอย่างเช่นฉันใช้เวลาในการทำให้องค์ประกอบทั้งหมดของอาร์เรย์เป็นโมฆะก่อนที่จะลบจริง ๆ
สิ่งนี้ไม่จำเป็น วิธีการทำงานของ Java GC คือการค้นหาวัตถุที่ไม่มีการอ้างอิงดังนั้นถ้าฉันมี Object x ที่มีการอ้างอิง (= ตัวแปร) a ที่ชี้ไปที่มัน GC จะไม่ลบเนื่องจากมีการอ้างอิง ไปยังวัตถุนั้น:
a -> x
หากคุณไม่มีอะไรเกิดขึ้น:
a -> null
x
ดังนั้นตอนนี้ x ไม่มีการอ้างอิงที่ชี้ไปและจะถูกลบ สิ่งเดียวกันนี้เกิดขึ้นเมื่อคุณตั้งค่า a อ้างอิงไปยังวัตถุอื่นที่ไม่ใช่ x
ดังนั้นถ้าคุณมีอาร์เรย์อาเรย์ที่อ้างอิงถึงออบเจ็กต์ x, y และ z และตัวแปรที่อ้างอิงถึงอาเรย์นั้นจะมีลักษณะดังนี้:
a -> arr -> x
-> y
-> z
หากคุณไม่มีอะไรเกิดขึ้น:
a -> null
arr -> x
-> y
-> z
ดังนั้น GC พบว่าไม่มีการตั้งค่าอ้างอิงและลบมันซึ่งทำให้โครงสร้างนี้แก่คุณ:
a -> null
x
y
z
ตอนนี้ GC พบ x, y และ z แล้วลบออกไป การอ้างอิงแต่ละรายการในอาเรย์จะไม่ทำให้ดีขึ้นมันจะใช้เวลาของ CPU และพื้นที่ในโค้ด (ซึ่งกล่าวว่าจะไม่ทำให้เสียหายได้มากไปกว่านั้น) GC จะยังคงสามารถทำงานได้ตามที่ควร )
เหตุผลที่ถูกต้องสำหรับต้องการเพิ่มหน่วยความจำจาก programm ใด ๆ (java หรือไม่) คือการทำให้หน่วยความจำเพิ่มเติมพร้อมโปรแกรมอื่น ๆ ในระดับระบบปฏิบัติการ หากแอปพลิเคชัน java ของฉันใช้งาน 250MB ฉันอาจต้องการบังคับให้ลงเหลือ 1MB และทำให้สามารถใช้งานแอปอื่น ๆ ได้ถึง 249MB
หากต้องการขยายคำตอบและความคิดเห็นโดย Yiannis Xanthopoulos และ Hot Licks (ขออภัยฉันยังไม่สามารถแสดงความคิดเห็นได้!) คุณสามารถตั้งค่าตัวเลือก VM เช่นตัวอย่างนี้:
-XX:+UseG1GC -XX:MinHeapFreeRatio=15 -XX:MaxHeapFreeRatio=30
ใน jdk 7 ของฉันนี้จะปล่อยหน่วยความจำ VM ที่ไม่ได้ใช้หากฮีปมากกว่า 30% ว่างหลังจาก GC เมื่อ VM ว่าง คุณอาจต้องปรับพารามิเตอร์เหล่านี้
ในขณะที่ฉันไม่เห็นมันเน้นในลิงค์ด้านล่างโปรดทราบว่านักสะสมขยะบางคนอาจไม่เชื่อฟังพารามิเตอร์เหล่านี้และโดยค่าเริ่มต้นจาวาอาจเลือกหนึ่งเหล่านี้สำหรับคุณหากคุณเกิดขึ้นมีมากกว่าหนึ่งหลัก (ดังนั้นอาร์กิวเมนต์ UseG1GC ด้านบน )
อัปเดต: สำหรับ java 1.8.0_73 ฉันได้เห็น JVM บางครั้งปล่อยจำนวนเล็กน้อยด้วยการตั้งค่าเริ่มต้น ดูเหมือนว่าจะทำเฉพาะในกรณีที่ไม่ได้ใช้กอง ~ ~ 70% .. ไม่ทราบว่ามันจะปล่อยเชิงรุกมากขึ้นหรือไม่ถ้าระบบปฏิบัติการมีหน่วยความจำกายภาพเหลือน้อย
ฉันได้ทำการทดลองกับสิ่งนี้แล้ว
เป็นความจริงที่System.gc();
แนะนำให้เรียกใช้ Garbage Collector เท่านั้น
แต่การโทรSystem.gc();
หลังจากตั้งค่าการอ้างอิงทั้งหมดnull
จะช่วยเพิ่มประสิทธิภาพและการยึดครองหน่วยความจำ
หากคุณต้องการจัดสรรและเพิ่มจำนวนหน่วยความจำอย่างแท้จริงคุณสามารถทำได้ด้วย ByteBuffers โดยตรง มีแม้กระทั่งวิธีที่ไม่สามารถพกพาได้เพื่อเพิ่มหน่วยความจำ
อย่างไรก็ตามตามที่ได้รับการแนะนำเพียงเพราะคุณต้องเพิ่มหน่วยความจำใน C ไม่ได้หมายความว่าควรทำเช่นนี้
หากคุณรู้สึกว่าคุณมีกรณีการใช้งานที่ดีฟรี () โปรดรวมไว้ในคำถามเพื่อที่เราจะได้เห็นว่าคุณกำลังทำอะไรอยู่มันน่าจะเป็นวิธีที่ดีกว่า
ทั้งหมดจากjavacoffeebreak.com/faq/faq0012.html
เธรดลำดับความสำคัญต่ำจะดูแลการรวบรวมขยะโดยอัตโนมัติสำหรับผู้ใช้ ในช่วงเวลาว่างเธรดอาจถูกเรียกใช้และสามารถเริ่มเพิ่มหน่วยความจำก่อนหน้านี้ที่จัดสรรให้กับวัตถุใน Java แต่ไม่ต้องกังวล - มันจะไม่ลบวัตถุของคุณ!
เมื่อไม่มีการอ้างอิงไปยังวัตถุมันจะกลายเป็นเกมที่ยุติธรรมสำหรับตัวเก็บขยะ แทนที่จะเรียกรูทีนบางอย่าง (เช่นฟรีใน C ++) คุณเพียงแค่กำหนดการอ้างอิงทั้งหมดให้กับวัตถุเป็นโมฆะหรือกำหนดคลาสใหม่ให้กับการอ้างอิง
ตัวอย่าง:
public static void main(String args[]) { // Instantiate a large memory using class MyLargeMemoryUsingClass myClass = new MyLargeMemoryUsingClass(8192); // Do some work for ( .............. ) { // Do some processing on myClass } // Clear reference to myClass myClass = null; // Continue processing, safe in the knowledge // that the garbage collector will reclaim myClass }
หากรหัสของคุณกำลังจะขอหน่วยความจำจำนวนมากคุณอาจต้องการขอให้ที่เก็บขยะเริ่มต้นการเรียกคืนพื้นที่แทนที่จะปล่อยให้มันเป็นเธรดที่มีลำดับความสำคัญต่ำ เมื่อต้องการทำสิ่งนี้ให้เพิ่มสิ่งต่อไปนี้ในรหัสของคุณ
System.gc();
ตัวรวบรวมขยะจะพยายามเรียกคืนพื้นที่ว่างและแอปพลิเคชันของคุณสามารถดำเนินการต่อโดยมีการเรียกคืนหน่วยความจำให้มากที่สุดเท่าที่จะทำได้ (ปัญหาการกระจายตัวของหน่วยความจำอาจใช้กับแพลตฟอร์มบางแห่ง)
ในกรณีของฉันเนื่องจากโค้ด Java ของฉันตั้งใจที่จะส่งไปยังภาษาอื่น ๆ ในอนาคตอันใกล้ (ส่วนใหญ่ C ++) ฉันอย่างน้อยฉันต้องการจ่ายค่าบริการปากเพื่อเพิ่มหน่วยความจำอย่างถูกต้องดังนั้นจึงช่วยกระบวนการย้ายในภายหลัง
ฉันเองพึ่งพาตัวแปรโมฆะเป็นตัวยึดตำแหน่งสำหรับการลบที่เหมาะสมในอนาคต ตัวอย่างเช่นฉันใช้เวลาในการลบล้างองค์ประกอบทั้งหมดของอาร์เรย์ก่อนที่จะลบ (ทำให้เป็นโมฆะ) อาร์เรย์
แต่กรณีของฉันมีความเฉพาะเจาะจงมากและฉันรู้ว่าฉันได้รับความนิยมในการแสดงเมื่อทำสิ่งนี้
* "ตัวอย่างเช่นสมมติว่าคุณประกาศรายการที่จุดเริ่มต้นของวิธีการที่ขยายขนาดให้ใหญ่มาก แต่จำเป็นต้องใช้จนกว่าจะถึงวิธีครึ่งทางในตอนนี้คุณสามารถตั้งค่าการอ้างอิงรายการเป็น null ได้ เพื่ออนุญาตให้ตัวรวบรวมขยะสามารถเรียกคืนวัตถุนี้ได้ก่อนที่วิธีการจะเสร็จสิ้น (และการอ้างอิงไม่อยู่ในขอบเขตอยู่แล้ว) " * * * *
สิ่งนี้ถูกต้อง แต่วิธีนี้อาจไม่สามารถใช้การได้ทั่วไป ในขณะที่การตั้งค่าการอ้างอิงวัตถุรายการเป็นโมฆะ - จะทำให้หน่วยความจำสำหรับการเก็บขยะนี้เป็นจริงสำหรับวัตถุรายการประเภทดั้งเดิม หากวัตถุรายการมีประเภทการอ้างอิงแทนการตั้งค่ารายการวัตถุ = null จะไม่ตรวจสอบ - ใด ๆ ของประเภทการอ้างอิงที่มีอยู่ในรายการ ในกรณีนี้การตั้งค่า List object = null จะทำให้กำพร้าประเภทการอ้างอิงที่มีอยู่ซึ่งวัตถุนั้นจะไม่พร้อมใช้งานสำหรับการรวบรวมขยะยกเว้นว่าอัลกอริทึมการรวบรวมขยะนั้นฉลาดพอที่จะระบุว่าวัตถุนั้นถูกกำพร้าแล้ว
Java Althrough ให้เก็บขยะอัตโนมัติบางครั้งคุณจะต้องการทราบว่ามีขนาดใหญ่วัตถุและวิธีการมากของมันถูกทิ้งหน่วยความจำด้วยการใช้ programatically import java.lang;
และRuntime r=Runtime.getRuntime();
จะได้รับค่าของหน่วยความจำโดยใช้mem1=r.freeMemory();
การเรียกหน่วยความจำฟรีr.gc();
วิธีการและการโทรfreeMemory()
คำแนะนำจาก JAVA คือกำหนดให้เป็นโมฆะ
จากhttps://docs.oracle.com/cd/E19159-01/819-3681/abebi/index.html
การกำหนดค่า Null อย่างชัดเจนให้กับตัวแปรที่ไม่ต้องการอีกต่อไปจะช่วยให้ตัวรวบรวมข้อมูลขยะสามารถระบุส่วนของหน่วยความจำที่สามารถเรียกคืนได้อย่างปลอดภัย แม้ว่า Java จะให้การจัดการหน่วยความจำ แต่ก็ไม่ได้ป้องกันหน่วยความจำรั่วหรือใช้หน่วยความจำมากเกินไป
แอปพลิเคชันอาจชักนำให้เกิดการรั่วไหลของหน่วยความจำโดยไม่ปล่อยการอ้างอิงวัตถุ การทำเช่นนี้จะป้องกันตัวรวบรวมขยะ Java จากการเรียกคืนวัตถุเหล่านั้นและส่งผลให้มีการใช้หน่วยความจำเพิ่มขึ้น การลบล้างการอ้างอิงตัวแปรอย่างชัดเจนหลังจากการใช้ทำให้ตัวรวบรวมขยะสามารถเรียกคืนหน่วยความจำได้
วิธีหนึ่งในการตรวจสอบการรั่วไหลของหน่วยความจำคือการใช้เครื่องมือการทำโปรไฟล์และถ่ายภาพหน่วยความจำหลังจากทำธุรกรรมแต่ละครั้ง แอปพลิเคชันที่ไม่มีการรั่วไหลในสถานะคงที่จะแสดงหน่วยความจำฮีปที่คงที่หลังจากการรวบรวมขยะ