程序計數器能夠看做是當前線程所執行的字節碼的行號指示器 線程私有 異常: 惟一一個java虛擬機規範中沒有規定任何OutOfMemoryError狀況的區域
線程私有,生命週期和線程相同 虛擬機棧描述的是Java方法執行的內存模型:每一個方法在執行的同時會建立一個棧幀用於存儲局部變量表、操做數棧、動態連接、方法出口等信息。局部變量表存放了編譯期可知的各類基本數據類型、對象引用。 異常: 線程請求的棧深度大於虛擬機所容許的深度,將拋出StackOverFlowError異常 若是虛擬機棧能夠動態擴展,若是擴展沒法申請到足夠的內存,就會拋出OOM
/** * 虛擬棧遞歸調用棧溢出(StackOverFlowError) * VM Args:-Xss512k */ public class JavaVMStackSOF { private int stackLenqth = 1; public void stackLeek() { stackLenqth++; //遞歸調用 stackLeek(); } public static void main(String[] args) { JavaVMStackSOF stackSOF = new JavaVMStackSOF(); stackSOF.stackLeek(); } } //結果 Exception in thread "main" java.lang.StackOverflowError at outofmemory.JavaVMStackSOF.stackLeek(JavaVMStackSOF.java:11)
/** * 建立線程致使OOM * VM Args: -Xss2M */ public class JavaVMStackOOM { private void dontStop(){ while (true){ } } public void stackLeakByThread(){ while (true){ Thread thread = new Thread(new Runnable() { public void run() { dontStop(); } }); thread.start(); } } public static void main(String[] args) { JavaVMStackOOM stackOOM = new JavaVMStackOOM(); stackOOM.stackLeakByThread(); } } //結果 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
全部線程共享 本地方法棧和Java虛擬棧類似,Java虛擬機棧爲虛擬機執行Java方法(字節碼)服務,本地方法棧爲虛擬機 用到的native方法服務。 HotSpot虛擬機將虛擬機棧和本地方法棧合二爲一
全部的對象實例和數組都要在堆上分配 Java堆是垃圾器管理的主要區域 異常: 堆中沒有內存完成實例分配,而且堆沒法在擴展的時,就會拋出OOM
/** * 堆內存溢出 * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError */ public class HeapOOM { static class OOMObject { } public static void main(String[] args) { List<OOMObject> list = new ArrayList<OOMObject>(); while (true) {//循環建立對象 list.add(new OOMObject()); } } } //運行結果 Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
全部線程共享 用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據 異常: 方法區沒法知足內存分配需求時,就會拋出OOM
方法區的一部分 用於存放編譯期生成的各類字面量和符號引用 Java並不要求常量必定要是編譯期才能產生,運行期間也可能將新的常量放入池中,好比String類的intern()方法 異常: 運行時常量池做爲方法區的一部分,天然收到方法去內存的限制,常量池沒法申請到內存拋出OOM
/** * 運行是常量池溢出 * VM Args: -XX:PermSize=10M -XX:MaxPermSize=10M */ public class RuntimeConstantPoolOOM { public static void main(String[] args) { List<String> stringList = new ArrayList<String>(); int i = 1; while (true){ stringList.add(String.valueOf(i++)); } } } //結果 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=10M; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=10M; support was removed in 8.0 // 分析 我使用的時jdk8.0發生如上錯誤,這個說明永久代已經在java8.0中被移除,被元空間替代。 關於爲啥要移除替代本篇不累贅。若是使用的jdk8.0一下版本則會出現OOM:PermGen space 這樣能夠證實常量池屬於方法區 //VM Args:-XX:MaxMetaspaceSize=2M(這樣設置元空間大小 )
直接內存不是虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域 NIO可使用Native函數庫直接分配堆外內存 異常: 本機內存不足拋出OOM
參考資料:《深刻理解Java虛擬機》java