س: كيف يمكن أن يحدث تسرب للذاكرة في Java؟
ج: في Java، هناك أسباب عديدة لتسرب الذاكرة. المثال النموذجي هو الكود الذي لا يطبق hasCode و
يتم حفظ الفئة الرئيسية لطريقة التساوي في HashMap. في النهاية، سيتم إنشاء العديد من الكائنات المكررة. كل تسرب الذاكرة
في النهاية، سيتم طرح استثناء OutOfMemoryError، وإليك محاكاة مختصرة لتسرب الذاكرة من خلال حلقة لا نهائية.
اشرح بمثال.
انسخ رمز الكود كما يلي:
import java.util.HashMap;
import java.util.Map;
الطبقة العامة MemoryLeak {
public static void main(String[] args) {
Map<Key, String> Map = new HashMap<Key, String>(1000);
عداد كثافة العمليات = 0؛
بينما (صحيح) {
// ينشئ كائنات مكررة بسبب فئة المفتاح السيئة
Map.put(new Key("dummyKey"), "value");
عداد++;
إذا (العداد % 1000 == 0) {
System.out.println("حجم الخريطة:" + Map.size());
System.out.println("الذاكرة الحرة بعد العد" + counter
+ "هو" + getFreeMemory() + "MB");
نوم(1000);
}
}
}
// مفتاح الفئة الداخلية بدون hashcode() أو يساوي() - تنفيذ سيء
مفتاح فئة ثابتة {
مفتاح سلسلة خاص؛
المفتاح العام (مفتاح السلسلة) {
this.key = key;
}
}
// التأخير لفترة معينة بالمللي ثانية
نوم الفراغ الثابت العام (نوم طويل For) {
يحاول {
Thread.sleep(sleepFor);
} قبض على (InterruptedException e) {
printStackTrace();
}
}
// احصل على الذاكرة المتوفرة بالميجابايت
public static long getFreeMemory() {
إرجاع Runtime.getRuntime().freeMemory() / (1024 * 1024);
}
}
والنتيجة هي كما يلي:
انسخ رمز الكود كما يلي:
حجم الخريطة: 1000
الذاكرة الحرة بعد العد 1000 هي 4 ميجابايت
حجم الخريطة: 2000
الذاكرة الحرة بعد العد 2000 هي 4 ميجابايت
حجم الخريطة: 1396000
الذاكرة الحرة بعد العد 1396000 هي 2 ميجابايت
حجم الخريطة: 1397000
الذاكرة الحرة بعد العد 1397000 هي 2 ميجابايت
حجم الخريطة: 1398000
الذاكرة الحرة بعد العد 1398000 هي 2 ميجابايت
حجم الخريطة: 1399000
الذاكرة الحرة بعد العد 1399000 هي 1 ميجابايت
حجم الخريطة: 1400000
الذاكرة الحرة بعد العد 1400000 هي 1 ميجابايت
حجم الخريطة: 1401000
الذاكرة الحرة بعد العد 1401000 هي 1 ميجابايت
.....
.....
حجم الخريطة: 1452000
الذاكرة الحرة بعد العد 1452000 هي 0 ميجابايت
حجم الخريطة: 1453000
الذاكرة الحرة بعد العد 1453000 هي 0 ميجابايت
استثناء في مؤشر الترابط "الرئيسي" 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 = key;
}
@تجاوز
منطقية عامة يساوي (كائن كائن) {
إذا (مثيل الكائن للمفتاح)
return key.equals(((مفتاح) obj).key);
آخر
عودة كاذبة.
}
@تجاوز
كود التجزئة العام () {
إرجاع المفتاح.hashCode();
}
}
.....
سيؤدي إعادة تنفيذ البرنامج إلى النتائج التالية:
انسخ رمز الكود كما يلي:
حجم الخريطة: 1
الذاكرة الحرة بعد العد 1000 هي 4 ميجابايت
حجم الخريطة: 1
الذاكرة الحرة بعد العد 2000 هي 4 ميجابايت
حجم الخريطة: 1
الذاكرة الحرة بعد العد 3000 هي 4 ميجابايت
حجم الخريطة: 1
الذاكرة الحرة بعد العد 4000 هي 4 ميجابايت
...
الذاكرة الحرة بعد العد 73000 هي 4 ميجابايت
حجم الخريطة: 1
الذاكرة الحرة بعد العد 74000 هي 4 ميجابايت
حجم الخريطة: 1
الذاكرة الحرة بعد العد 75000 هي 4 ميجابايت
س: في السيناريوهات الفعلية، كيف يمكنك العثور على تسرب الذاكرة؟
ج: احصل على معرف الموضوع من خلال الكود التالي
انسخ رمز الكود كما يلي:
ج:/> جبس
5808 جبس
4568 تسرب الذاكرة
3860 الرئيسي
افتح jconsole عبر سطر الأوامر
انسخ رمز الكود كما يلي:
ج:/> جسكونسول 4568
فئة المفتاح التي تنفذ hasCode وequals والمخطط الذي لا ينفذها هي كما يلي:
لا يوجد تسرب للذاكرة:
سبب تسرب الذاكرة: