java 堆溢出:java
在eclipse中測試時,能夠在Debug/Run中設置虛擬機參數,好比-xmx 20M 表明虛擬機堆內存大小最大值是20M,-xms是最小堆內存。而後寫個死循環測試類不斷在List集合中添加對象, 當堆內存超出20M ,會報OutOfMemory異常。框架
虛擬機棧和本地方法棧溢出:eclipse
一個線程中若是,方法的深度超過了虛擬機容許的深度 ,會報StackOverFlow異常,好比遞歸調用方法。這個異常容易去實現,另外一種是java虛擬機棧在擴展時若是沒法申請到內存,則會報OutOfMemory異常。測試
public class Main { private static int count=0; public static void main(String[] args) { // TODO Auto-generated method stub try{ deap(); }catch(Exception ex){ ex.printStackTrace(); } } private static void deap(){ count++; System.out.println(count); deap(); } }
在設置-Xss爲1M 和 10M時, 輸出的計數變量會差10倍左右,個人理解是虛擬機棧運行時其實就是java方法執行時內存模型,在無止境的遞歸時會向虛擬機棧中壓入棧幀用於存儲執行時的操做數,局部變量方法出口等信息。當這塊內存滿時,就會報棧溢出。
spa
操做系統中系統限制了每個進程的內存上限, 若是規定每一個進程的內存大小上限爲1GB, 那麼在虛擬機中,方法區內存和堆內存能夠經過虛擬機參數設置(xmx和 maxPerSize),虛擬機進程內存減去 堆內存和方法區的總內存,若是忽略計數器和虛擬機自己執行所消耗的內存(這兩部分佔的內存很小),基本上剩下的內存會被虛擬機棧和本地方法棧瓜分。 每個線程分配到的虛擬機棧內存越大,那麼能夠建立的線程數量就越少。
操作系統
3.方法區和運行時常量池溢出:線程
方法區內存大小設置能夠經過虛擬機參數 -XX:PermSize 和 -XX:MaxPermSize來設置,java 1.6環境中如下代碼能夠實現方法區常量池內存溢出:
code
public static void main(String[] args) { // TODO Auto-generated method stub int i=0; ArrayList<String> list=new ArrayList<String>(); while(true){ list.add(String.valueOf(i++).intern()); } }
這裏String.intern()方法的做用是字符串常量池中若是存在一個等於這個String對象的字符串,則返回引用,不然會將此字符串存入常量池,java 1.6中常量池是分配在永久代內存中,gc幾乎不會去回收,因此常量池內存會溢出(1.7 虛擬機中已將字符串常量池從永久代移除), 填充方法區內存可使用gclib來建立大量的類,由於方法區用於存放類Class的相關信息用的,好比類名,訪問修飾符,常量池等, Spring,OSGI等主流框架會遇到這樣的問題,這類框架都須要加載大量的類,而回收一個類斷定條件比較苛刻,在方法區內存分配小時會報OutOfMemoryError:PerGen space異常,即方法區溢出。對象
4.本機內存溢出:
blog
DirectMemory 容量能夠經過設置虛擬機參數 -XX:MaxDirectMemorySize來設定,實驗方法: 設置了直接內存上限後,不斷地經過unsafe類的allocateMemory()方法去申請內存,當達到上限時會報:OutOfMemory異常.
參考鏈接:
http://lavasoft.blog.51cto.com/62575/25492/