1. 程式人生 > >內存泄漏與內存溢出

內存泄漏與內存溢出

hash tag 最終 對象引用 變化 申請 close hashcode mem

內存溢出 out of memory,是指程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;

內存泄露 memory leak,是指程序在申請內存後,無法釋放已申請的內存空間,一次內存泄露危害可以忽略,但內存泄露堆積後果很嚴重,無論多少內存,遲早會被占光。

## memory leak會最終會導致out of memory!


內存泄漏

長生命周期的對象引用短聲明周期的對象,導致短生命周期的對象在生命周期已結束後還無法回收對象內存 ,造成內存泄漏

場景

  • 1、靜態集合引用對象
public class dome1 {
    static Set<Object> s = new HashSet(10);
    public static void main(String[] args) {

        for (int i = 0; i < 100; i++) {
            Object o = new Object();
            s.add(o);
            //對象賦值位空值,理應被垃圾回收器回收,但是被集合引用,
            // 但是GC-Roots 到對象之間存在引用鏈(可到達),
            //所以不會被回收內存
            o = null;
        }
        s.forEach(System.out::println);
    }
}
  • 2、集合裏面的對象屬性被修改,在調用remove()方法時不起作用,造成對象刪除不掉,造成內存泄漏
HashSet<Person> set = new HashSet<>();
Person tom = new Person(1L, "Tom", 12);
System.out.println(tom.hashCode());//2613467
set.add(tom);
tom.setAge(13);//修改對象的屬性後對象的hashCode發生變化
System.out.println(tom.hashCode());//2613468
System.out.println(set.remove(tom));//false  remove不成功,造成內存泄漏
set.forEach(System.out::println);
System.out.println(set.add(tom));// true  添加成功,判斷是否相等時驗證hashCode
set.forEach(System.out::println);
  • 3、監聽器未刪除

  • 4、各種連接為關閉

數據庫鏈接、網絡鏈接、IO鏈接必須顯式的調用close關閉鏈接,否則不會被GC回收

  • 5、內部類和外部模塊的引用

  • 6、單例模式引用其他對象
    單例模式為靜態資源,整個JVM生命周期都有效,如果單例對象持有對外部對象的引用,那麽這個外部對象不會被GC回收,導致內存泄漏
if (true){
    Person tom = new Person(1L, "Tom", 12);
    singleton.getInstance().setPerson(tom);
}
System.out.println(singleton.getInstance().getPerson());

對象tom已經結束生命周期,但是被單例對象引用,不會被GC回收

二、內存溢出

在Java堆中不斷的創建對象造成

大量的內存泄漏

內存泄漏與內存溢出