Java內存區域與內存溢出異常

Java內存區域與內存溢出異常

  • 運行時數據區域 輸入圖片說明
    • 程序計數器
      • 記錄當前線程執行的字節碼的行號(指令地址)
      • 線程私有
      • 惟一一個沒有規定任何OutOfMemoryError的區域
    • Java虛擬機棧
      • 線程私有
      • Java方法執行的內存模型:方法執行時,會建立一個棧幀,存儲局部變量表、操做數棧、動態連接、方法出口等信息。
      • 咱們平時說的「棧內存」,是指Java虛擬機棧中的局部變量表。變量局部表存儲基本數據類型、對象引用類型。
      • 兩種異常
        • 線程請求的棧深度大於虛擬機所容許的深度,拋出StackOverflowError異常
        • 虛擬機棧動態擴展時,沒法申請到足夠的內存,拋出OutOfMemoryError異常
    • 本地方法棧
      • 虛擬機棧爲虛擬機執行Java方法服務
      • 本地方法棧爲虛擬機使用到的Native方法服務,做用於虛擬機棧類似
      • 拋出StackOverflowError和OutOfMemoryError異常
    • Java堆
      • 全部線程共享,存放對象實例
      • 堆內沒有內存完成實例分配,而且堆也沒法擴展時,拋出OutOfMemoryError異常
    • 方法區
      • 全部線程共享
      • 存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據
      • 方法區沒法知足內存分配需求時,將拋出OutOfMemoryError異常
  • OutOfMemoryError異常
    • Java堆溢出
      • 代碼
      public class HeapOOM {
          static class OOMObject {
      
          }
      
          public static void main(String[] args) {
              List<OOMObject> list = new ArrayList<>();
              while (true) {
                  list.add(new OOMObject());
              }
          }
      }
      • 設置虛擬機參數
        -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\Users\xxx\Desktop
      • 異常以下
        Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:3210)
        at java.util.Arrays.copyOf(Arrays.java:3181)
        at java.util.ArrayList.grow(ArrayList.java:261)
        at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
        Heap dump file created [28207505 bytes in 0.158 secs]
        at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
        at java.util.ArrayList.add(ArrayList.java:458)
        at HeapOOM.main(HeapOOM.java:15)
      • 分析異常
        • 將dump下來的堆轉儲快照文件導入Eclipse Memory Analyzer工具
        • 點擊Histogram查看類對象佔用的空間大小,以下
          輸入圖片說明
        • 程序經過不斷的建立OOMObject對象,致使堆被迅速的佔滿,從而出現堆內存溢出
    • 虛擬機棧和本地方法棧溢出
      • 代碼
      public class JavaVMStackSOF {
          private int stackLength = 1;
      
          public void stackLeak() {
              stackLength++;
              stackLeak();
          }
      
          public static void main(String[] args) {
              JavaVMStackSOF oom = new JavaVMStackSOF();
              try {
                  oom.stackLeak();
              } catch (Exception e) {
                  System.out.println("stack length:" + oom.stackLength);
                  e.printStackTrace();
              }
          }
      }
      • 虛擬機參數:-Xss128k
      • 異常以下
      Exception in thread "main" java.lang.StackOverflowError
      	at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8)
      	at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
      	at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
      	at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
      	at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
      	at JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:9)
      ........
    • 方法區和運行時常量池溢出
      • 代碼
      public class RuntimeConstantPoolOOM {
          public static void main(String[] args) {
              List<String> list = new ArrayList<>();
              int i = 0;
              while (true) {
                  list.add(String.valueOf(i++).intern());
              }
          }
      }
      • 虛擬機參數:-Xms10m -Xmx10m
      • 異常以下
      Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
      	at java.lang.Integer.toString(Integer.java:403)
      	at java.lang.String.valueOf(String.java:3099)
      	at RuntimeConstantPoolOOM.main(RuntimeConstantPoolOOM.java:12)
相關文章
相關標籤/搜索