java堆用於存儲對象實例,只要不斷建立對象,而且保證GC Roots到對象之間的可達路徑來避免垃圾回收機制清理這些對象,那麼當對象的達到堆的容量最大值滯後就會產生outofmemoryerror;java
經過參數:-Xms20m 最小堆大小; -Xmx20m 最大堆大小; -XX:+HeapDumpOnOutOfMemoryError 虛擬機在內存溢出異常時Dump出當前的內存堆轉儲快照windows
具體配置:ide
-verbose:gc -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDetails -XX:SurvivorRatio=8
代碼:測試
1 package javaTest; 2 3 import java.io.Serializable; 4 import java.util.LinkedList; 5 import java.util.List; 6 7 public class Portal { 8 9 /** 10 * vm args : -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError 11 * @param args 12 */ 13 public static void main(String[] args) { 14 System.out.println("test heap memory dump"); 15 16 17 List<HeapOOM> lists = new LinkedList<HeapOOM>(); 18 19 while(true){ 20 lists.add(new HeapOOM()); 21 } 22 23 24 25 } 26 27 public static class HeapOOM implements Serializable{ 28 29 /** 30 * 31 */ 32 private static final long serialVersionUID = -7562967142125991489L; 33 34 private int count; 35 36 public int getCount() { 37 return count; 38 } 39 40 public void setCount(int count) { 41 this.count = count; 42 } 43 44 45 } 46 47 }
異常:this
注意:必定要辨別是內存泄露(memory Leak)仍是內存溢出(memory Overflow)spa
若是線程請求的棧深度大於虛擬機所容許的最大深度,將拋出StackOverFlowError異常;線程
若是虛擬機的擴展棧沒法申請到足夠的內存空間,則拋出OutOfMemoryError異常;3d
參數:-Xoss 設置本地方法棧大小;-Xss 設置虛擬機房發展大小code
具體設置:對象
-Xss128k
代碼:
1 package javaTest; 2 3 public class StackOverFlowTest { 4 5 /** 6 * vm args : -Xss128K 7 * @param args 8 */ 9 public static void main(String[] args){ 10 11 OverFlowStackClass model = new OverFlowStackClass(); 12 13 try{ 14 model.stackLeak(); 15 }catch(Throwable ex){ 16 System.out.println("最大深度:"+String.valueOf(model.stackLength)); 17 throw ex; 18 } 19 20 21 22 23 24 25 } 26 27 static class OverFlowStackClass{ 28 public int stackLength=1; 29 30 public void stackLeak(){ 31 stackLength++; 32 stackLeak(); 33 } 34 } 35 36 37 38 }
異常:
若是是建立過多的線程致使內存溢出,在不減小線程數量或者更換64bit虛擬機的狀況下,就只能經過減小最大堆和減小虛擬機棧容量來換取更多的線程,若是沒有這方便的處理經驗,這種經過增長線程擠佔java虛擬機棧的方式來驗證java棧的內存溢出(outofmemoryerror)的場景是很難想到的;
本人電腦是windows這裏對於這種狀況就不作演示了,代碼實現其實就是瘋狂的建立新的線程來實現。java棧的內存溢出;
String.intern();是一個Native方法,它的做用是 若是字符串常量池中已經包含一個等於此String對象的字符串,則返回字符串常量池中的這個字符串;不然建立一個新的對象,該對象添加到常量池中,最後返回此字符串的引用。
參數:-XX:PermSize -XX:MaxPermSize
具體參數:
-XX:PermSize=10M -XX:MaxPermSize=10M
代碼:
1 package javaTest; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 public class MethodOutOfMemoryError { 7 8 /** 9 * vm args: -XX:PermSize=10M -XX:MaxPermSize=10M 10 * @param args 11 */ 12 public static void main(String[] args){ 13 14 List<String> lists = new ArrayList<String>(); 15 16 int i=0; 17 while(true){ 18 lists.add(String.valueOf(i++).intern()); 19 } 20 21 } 22 23 }
異常:
1.7+以上版本不會出現異常了,能夠經過:-verbose:gc查看GC的回收過程;
參數:-XX:MaxDirectMemorySize 制定可使用的機器內存的大小
具體運行參數:
-Xmx10m -XX:MaxDirectMemorySize=10m
代碼:
1 package javaTest; 2 3 import java.lang.annotation.Annotation; 4 import java.lang.reflect.Field; 5 6 import sun.misc.Unsafe; 7 8 public class DirectMemoryTest { 9 10 private static final int _1MB = 1024*1024; 11 12 /** 13 * vm agrs: -Xmx10m -XX:MaxDirectMemorySize=10m 14 * @param args 15 * @throws IllegalAccessException 16 * @throws IllegalArgumentException 17 */ 18 public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException{ 19 20 System.out.println(_1MB); 21 22 Field unsafeField = Unsafe.class.getDeclaredFields()[0]; 23 unsafeField.setAccessible(true); 24 Unsafe unsafe = (Unsafe)unsafeField.get(null); 25 while(true){ 26 unsafe.allocateMemory(_1MB); 27 } 28 29 30 31 32 } 33 }
異常:
雖然java有垃圾回收機制,可是內存溢出對咱們來講也是屢見不鮮,因此要明白什麼狀況下致使內存溢出,從而儘可能避免內存溢出的發生;
若是出現內存異常根據堆棧信息能夠快速排查是什麼緣由;