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)
相关文章
相关标签/搜索