ถาม: หน่วยความจำรั่วเกิดขึ้นใน Java ได้อย่างไร
ตอบ: ใน Java มีสาเหตุหลายประการที่ทำให้หน่วยความจำรั่ว ตัวอย่างทั่วไปคือโค้ดที่ไม่ได้ใช้ hasCode และ
คลาสคีย์ของเมธอดเท่ากับจะถูกบันทึกใน HashMap ในท้ายที่สุด จะมีการสร้างวัตถุที่ซ้ำกันจำนวนมาก หน่วยความจำรั่วทั้งหมด
ในท้ายที่สุด ข้อยกเว้น OutOfMemoryError จะถูกส่งออกไป ต่อไปนี้เป็นการจำลองโดยย่อของหน่วยความจำรั่วผ่านการวนซ้ำไม่สิ้นสุด
อธิบายด้วยตัวอย่าง
คัดลอกรหัสรหัสดังต่อไปนี้:
นำเข้า java.util.HashMap;
นำเข้า java.util.Map;
MemoryLeak คลาสสาธารณะ {
โมฆะคงที่สาธารณะ main (String [] args) {
แผนที่ <คีย์, สตริง> แผนที่ = ใหม่ HashMap <คีย์, สตริง> (1,000);
ตัวนับ int = 0;
ในขณะที่ (จริง) {
// สร้างวัตถุที่ซ้ำกันเนื่องจากคลาสคีย์ไม่ดี
map.put(คีย์ใหม่("dummyKey"), "value");
เคาน์เตอร์++;
ถ้า (ตัวนับ % 1,000 == 0) {
System.out.println("ขนาดแผนที่: " + map.size());
System.out.println("หน่วยความจำว่างหลังนับ" + counter
+ " คือ " + getFreeMemory() + "MB");
นอนหลับ(1,000);
-
-
-
// คีย์คลาสภายในที่ไม่มี hashcode() หรือเท่ากับ() -- การใช้งานที่ไม่ถูกต้อง
คีย์คลาสคงที่ {
สตริงคีย์ส่วนตัว
คีย์สาธารณะ (คีย์สตริง) {
this.key = คีย์;
-
-
// หน่วงเวลาในช่วงเวลาที่กำหนดในหน่วยมิลลิวินาที
การนอนหลับเป็นโมฆะสาธารณะแบบคงที่ (sleep ยาวสำหรับ) {
พยายาม {
Thread.sleep(sleepFor);
} จับ (InterruptedException e) {
e.printStackTrace();
-
-
//รับหน่วยความจำที่มีอยู่เป็น MB
getFreeMemory ยาวคงที่สาธารณะ () {
กลับ Runtime.getRuntime().freeMemory() / (1024 * 1024);
-
-
ผลลัพธ์จะเป็นดังนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
ขนาดแผนที่: 1,000
หน่วยความจำว่างหลังจากนับ 1,000 คือ 4MB
ขนาดแผนที่: 2000
หน่วยความจำว่างหลังจากนับ 2,000 คือ 4MB
ขนาดแผนที่: 1396000
หน่วยความจำว่างหลังจากนับ 1396000 คือ 2MB
ขนาดแผนที่: 1397000
หน่วยความจำว่างหลังจากนับ 1397000 คือ 2MB
ขนาดแผนที่: 1398000
หน่วยความจำว่างหลังจากนับ 1398000 คือ 2MB
ขนาดแผนที่: 1399000
หน่วยความจำว่างหลังจากนับ 1399000 คือ 1MB
ขนาดแผนที่: 1400000
หน่วยความจำว่างหลังจากนับ 1400000 คือ 1MB
ขนาดแผนที่: 1401000
หน่วยความจำว่างหลังจากนับ 1401000 คือ 1MB
-
-
ขนาดแผนที่: 1452000
หน่วยความจำว่างหลังจากนับ 1452000 คือ 0MB
ขนาดแผนที่: 1453000
หน่วยความจำว่างหลังจากนับ 1453000 คือ 0MB
ข้อยกเว้นในเธรด "main" java.lang.OutOfMemoryError: พื้นที่ฮีป Java
ที่ java.util.HashMap.addEntry(HashMap.java:753)
ที่ java.util.HashMap.put(HashMap.java:385)
ที่ MemoryLeak.main(MemoryLeak.java:10)
ถาม: จะแก้ไขหน่วยความจำรั่วข้างต้นได้อย่างไร
ตอบ: ใช้เมธอดเท่ากับและ hasCode ของคลาสคีย์
คัดลอกรหัสรหัสดังต่อไปนี้:
-
คีย์คลาสคงที่ {
สตริงคีย์ส่วนตัว
คีย์สาธารณะ (คีย์สตริง) {
this.key = คีย์;
-
@แทนที่
บูลีนสาธารณะเท่ากับ (Object obj) {
ถ้า (obj อินสแตนซ์ของคีย์)
return key.equals(((คีย์) obj).key);
อื่น
กลับเท็จ;
-
@แทนที่
hashCode int สาธารณะ () {
กลับคีย์ hashCode();
-
-
-
การรันโปรแกรมอีกครั้งจะให้ผลลัพธ์ดังต่อไปนี้:
คัดลอกรหัสรหัสดังต่อไปนี้:
ขนาดแผนที่: 1
หน่วยความจำว่างหลังจากนับ 1,000 คือ 4MB
ขนาดแผนที่: 1
หน่วยความจำว่างหลังจากนับ 2,000 คือ 4MB
ขนาดแผนที่: 1
หน่วยความจำว่างหลังจากนับ 3000 คือ 4MB
ขนาดแผนที่: 1
หน่วยความจำว่างหลังจากนับ 4000 คือ 4MB
-
หน่วยความจำว่างหลังจากนับ 73000 คือ 4MB
ขนาดแผนที่: 1
หน่วยความจำว่างหลังจากนับ 74000 คือ 4MB
ขนาดแผนที่: 1
หน่วยความจำว่างหลังจากนับ 75000 คือ 4MB
ถาม: ในสถานการณ์จริง คุณจะค้นหาหน่วยความจำรั่วได้อย่างไร
ตอบ: รับรหัสเธรดผ่านรหัสต่อไปนี้
คัดลอกรหัสรหัสดังต่อไปนี้:
C:/>jps
5808จป
4568 เมมโมรี่ลีค
3860 หลัก
เปิด jconsole ผ่านทางบรรทัดคำสั่ง
คัดลอกรหัสรหัสดังต่อไปนี้:
C:/>jconsole 4568
คลาสคีย์ที่ใช้ hasCode และเท่ากับ และแผนภูมิที่ไม่ได้ใช้มีดังนี้:
ไม่มีหน่วยความจำรั่ว:
ทำให้หน่วยความจำรั่ว: