jvm中除了程序計數器其餘運行時區域的OutOfMemoryError

1. java堆溢出測試

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 }
View Code

異常:this

注意:必定要辨別是內存泄露(memory Leak)仍是內存溢出(memory Overflow)spa

2. java虛擬機棧和本地方法棧溢出

若是線程請求的棧深度大於虛擬機所容許的最大深度,將拋出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 }
View Code

異常:

若是是建立過多的線程致使內存溢出,在不減小線程數量或者更換64bit虛擬機的狀況下,就只能經過減小最大堆和減小虛擬機棧容量來換取更多的線程,若是沒有這方便的處理經驗,這種經過增長線程擠佔java虛擬機棧的方式來驗證java棧的內存溢出(outofmemoryerror)的場景是很難想到的;

本人電腦是windows這裏對於這種狀況就不作演示了,代碼實現其實就是瘋狂的建立新的線程來實現。java棧的內存溢出;

3. 方法區和運行時常量池的內存溢出

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 }
View Code

異常:

1.7+以上版本不會出現異常了,能夠經過:-verbose:gc查看GC的回收過程;

4. 本機直接內存溢出

參數:-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 }
View Code

異常:

雖然java有垃圾回收機制,可是內存溢出對咱們來講也是屢見不鮮,因此要明白什麼狀況下致使內存溢出,從而儘可能避免內存溢出的發生;

 若是出現內存異常根據堆棧信息能夠快速排查是什麼緣由;

 

 

相關文章
相關標籤/搜索