Java記憶體地區與記憶體溢出異常,java地區溢出
1,java堆溢出
JAVA堆用於儲存物件執行個體,只要不斷的建立對象,保證GC Roots到對象直接有可達路徑,避免記憶體回收機制清楚對象,那麼對象數量叨叨一定程度後,會產生記憶體溢出異常。
如下代碼,限制Java堆大小為1024m,並且-Xms和-Xmx的參數相同,即不可擴充。同事在Run Configuration中增加VM 參數:
-XX:+HeapDumpOnOutOfMemoryError
讓虛擬機器在出現記憶體溢出異常時,Dump出當前的記憶體堆轉儲快照。
package com.jvm.exception;
import java.util.ArrayList;
import java.util.List;
public class HeapSpaceException {
public static void main(String[] args) {
List<byte[]> byteList = new ArrayList<byte[]>();
while(true){
byteList.add(new byte[1024]);
}
}
}
運行結果:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid2783.hprof ...
Heap dump file created [3795151132 bytes in 3.289 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at com.jvm.exception.HeapSpaceException.main(HeapSpaceException.java:13)
記憶體中首先提示OutOfMemoryError,讓後提升Java heap space。
一般出現此類問題,可以採用記憶體分析工具,如Eclipse Memory Analyzer進行分析。
如果記憶體泄露,則查看泄露對象到GC Roots的引用鏈,確定記憶體泄露位置。
如果記憶體未泄露,則應當檢查虛擬機器的參數(-Xmx 和 -Xms)。
2,虛擬機器棧和本地方法棧溢出
由於HotSpot虛擬機器並沒有區分虛擬機器棧和本地方法棧,因此對HotSpot來說,-Xoss(設定本地方法棧大小)參數存在,但實際是無效的。棧容量只能通過-Xss參數設定。虛擬機器棧和本地方法棧,在Java虛擬機器規範中定義了兩種異常:
-1,如果線程請求棧深度大於虛擬機器所允許的最大深度,將拋出StackOverFlowError異常。
-2,如果虛擬機器找擴充棧時無法申請到足夠的記憶體空間,則拋出OutOfMmemoryError。
首先在單線程環境中,使用-Xss參數減少棧記憶體容量,拋出StackOverFlowError。
package com.jvm.exception;
/**
* 預設-Xss參數
* @author jinglongjun
*
*/
public class StackOverFlowError {
private int stackLength = 1;
public void stackLeak(){
stackLength ++;
stackLeak();
}
public static void main(String[] args) {
StackOverFlowError sof = new StackOverFlowError();
try{
sof.stackLeak();
}catch(Throwable e){
System.out.println("stackLength : " + sof.stackLength);
throw e;
}
}
}
輸出內容:
stackLength : 10828
Exception in thread "main" java.lang.StackOverflowError
at com.jvm.exception.StackOverFlowError.stackLeak(StackOverFlowError.java:13)
at com.jvm.exception.StackOverFlowError.stackLeak(StackOverFlowError.java:14)
單線程環境,定義大量本地變數,增大方法棧中本地變數表的長度。結果拋出StackOverFlowEoor時,輸出的堆棧深度相應的縮小。
這種情況類比了很久沒有類比出來。因為本文是參考《深入理解Java虛擬機器》這本書的,書中也未給出例子。
在單線程下,總是拋出StackOverFlowError。
多線程類比。
建議不要嘗試運行下面的代碼。
建議不要嘗試運行下面的代碼。
建議不要嘗試運行下面的代碼。
package com.jvm.exception;
public class OutOfMemoryError {
public void dontStop(){
while(true){
}
}
public void stackLengthThread(){
while(true){
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
dontStop();
}
});
thread.start();
}
}
public static void main(String[] args) {
OutOfMemoryError oome = new OutOfMemoryError();
oome.stackLengthThread();
}
}
以上代碼會拋出:
OutOfMemoryError。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。