內存泄露與內存溢出

1、什麼是內存泄露java

內存泄露是指一個不在被程序使用的對象或變量還在內存中佔有存儲空間。數據庫

1. 內存泄露主要有兩種狀況:網絡

       (1). 在堆中申請的空間沒有釋放工具

       (2.) 該對象已經再也不使用,卻還在內存中保留着this

通常垃圾回收機制能夠有效的解決第一種狀況。spa

Java內存泄露主要是第二種狀況。線程

1 Vector v = new Vector();
2 for ( int i=0 ;i<10; i++ ){
3     Object o = new Object();
4     v.add(o);
5 }

在循環中不斷建立對象加入到Vector對象中,退出循環後o的做用域將會結束,日誌

在v中使用這些對象,垃圾回收器沒法回收,形成內存泄露。只有將這些對象從code

vector中刪除才能釋放這些對象。對象

2. 泄露緣由

(1)靜態集合類。例如 HashMap 和 Vector 。若是這些容器爲靜態的static,他們

的生命週期和程序一致,那麼容器中的對象在程序結束以前不能被釋放,從而形成

內存泄露。也就是長生命週期對象持有短生命週期的對象。

(2)各類鏈接。如數據庫鏈接、IO鏈接、網絡鏈接等。須要先創建鏈接,不使用時

要使用 close() 釋放鏈接,只有關閉鏈接後垃圾回收器纔會回收對應的對象,不然會

有大量對象沒法回收二形成內存泄露。

(3)監聽器。一般一個應用中用到多個監聽器,當釋放對象時,每每沒有刪除相應

的監聽器,而形成內存泄露。

(4)變量做用域不合理。若是一個變量的做用域大於其使用的範圍,可能會形成內

存泄露。如:

1 Class Server{
2      private String msg;
3      public void receiveMsg(){
4          readFromNet();//從網絡中接收msg
5          saveDB();//保存msg到數據庫
6     }
7 }

從網絡中接收msg而後保存到數據庫以後msg就沒用了,可是msg生命週期和對象的

生命週期相同,因此不會馬上被回收,形成內存泄露。

(5)單例模式可能會形成內存泄露。

 1 public class BigClass{
 2   //code
 3 }
 4 public class Singleton {
 5     private Singleton(BigClass bc){
 6         this.bc = bc;
 7     }
 8     private BigClass bc;
 9     private static Singleton instance = new Singleton(new BigClass());
10     public Singleton getInstance(){
11         return instance;
12     }
13 }

單例模式Singleton存在一個對對象 bc 的引用,可是單例instance對象以靜態方式存儲,它

在JVM整個生命週期都存在,bc沒法被回收,致使內存泄露。

3. 內存泄露的解決方案:

(1)避免在循環中建立對象

(2)最先釋放無用對象

(3)儘可能少用靜態變量,由於靜態變量在永久代,不多參加垃圾回收。

(4)使用字符串處理避免使用String,而用StringBuffer。

4.如何查找內存泄露

使用Jconsole。

2、什麼是內存溢出

指的是程序運行過程當中沒法申請到足夠的內存空間而致使的一種錯誤。

1. 內存溢出的幾種狀況:

除了程序計數器外,虛擬機其餘幾個運行時區域均可能發生OutOfMemorryError(OOM)異常。

(1)虛擬機棧和本地方法棧溢出

  若是線程請求的棧深度大於虛擬機所容許的最大深度, 將拋出
  StackOverflowError 異常。
  若是虛擬機在擴展棧時沒法申請到足夠的內存空間, 則拋出
  OutOfMemoryError 異常。

(2)堆溢出

  通常的異常信息:java.lang.OutOfMemoryError:Java heap spaces。

  檢查虛擬機的參數(-Xmx 與-Xms)的設置是否適當

(3)方法區溢出
  異常信息:java.lang.OutOfMemoryError:PermGen space。
(4)運行時常量池溢出
  異常信息:java.lang.OutOfMemoryError:PermGen space。
  若是要向運行時常量池中添加內容, 最簡單的作法就是使用
  String.intern()這個Native 方法。該方法的做用是:若是池中已經包含一個
  等於此String 的字符串,則返回表明池中這個字符串的String 對象;不然,
  將此String 對象包含的字符串添加到常量池中,而且返回此String 對象的引
  用。

 2. 內存溢出的緣由

(1)內存中加載的數據過於龐大,如一次從數據庫取出過多數據

(2)集合類中對對象的引用,使用完未清除,JVM沒法回收

(3)代碼中存在死循環或循環產生過多重複的對象實體

(4)啓動參數內存值設置太小

3.內存溢出解決辦法

(1)修改JVM啓動參數,直接增長內存

通常要將-Xms 和-Xmx 選項設置爲相同,以免在每次GC 後調整堆的大小;建
議堆的最大值設置爲可用內存的最大值的80%

(2)檢查錯誤日誌,查看 「outOfMemory」 錯誤前是否有其餘異常或錯誤

(3)使用內存查看工具動態查看內存使用狀況(Jconsole)。

擴展:基本上若是拋出OutOfMemory 有兩種緣由:1.內存泄露。2.應用程序自己就是須要這麼多的內存。

相關文章
相關標籤/搜索