Java內存泄露和溢出

基本概念

內存泄露:程序中動態分配內存給臨時對象,但是對象不會被GC所回收,它始終佔用內存。從而引發內存溢出

內存溢出:程序運行過程中無法申請到足夠的內存而導致的一種錯誤。

內存泄露是導致內存溢出的一種誘因,但不是唯一的因素。



Java堆溢出(OutOfMemoryError:Java heap space)

堆是用來存儲對象實例的,因此如果我們不斷地創建對象,並且使創建的對象不被垃圾回收,那麼當創建的對象過多時,會導致heap內存不足,進而引發OutOfMemoryError異常。

public static void main(String arg[]){

List<Integer> list = new ArrayList<>();

int i=0;

while(true){

list.add(i++);

}

}

上面是一個引發OutOfMemoryError異常的代碼。

通過java -Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryError設置堆內存爲10M,

參數-XX:+HeapDumpOnOutOfMemoryError 異常時打印當前的內存快照以便於後續分析。


Java棧異常(StackOverflowError)

JVM運行時數據區中有一個虛擬機棧的內存區域,此區域的作用是:每個方法在執行時都會創建一個棧幀,用於存儲局部變量,操作數棧,方法出口等信息。一秀線程棧溢出是由於遞歸太深或方法調用層級過多導致的。

public static void main(String arg[]){

test(1);

}

public static void test(int i){

i++;

test(i);

}

以上的代碼創建了一個無限遞歸的調用,當遞歸深度過大時,就會耗盡棧空間,進而導致StackOverflowError異常。


方法區內存溢出(OutOfMemoryError:PermGen space

在JVM中,方法區主要存放的是類信息、常量、靜態變量等。

如果程序加載的類過多,或者使用反射、GCLIB等這種動態代理生成類的技術,就可能導致方法區發生內存溢出。


避免內存泄露:

1、儘早釋放無用的對象引用

2、字符串處理避免使用String,改用StringBuffer,每一個String對象都佔用一塊獨立的內存

3、儘量少用靜態變量,因爲靜態變量存放在永久代(方法區),永久代基本不參與垃圾回收

4、避免在循環中創建對象

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章