Java内存区域与内存溢出异常

Java内存区域与内存溢出异常

Scroll Down

Java内存区域与内存溢出异常

运行时数据区

  • 方法区(Method Area)
  • 虚拟机栈(VM Stack)
  • 本地方法栈(Native Method Stack)
  • 堆(Heap)
  • 程序计数器(PC)

image-20200531233651304

Tips:方法区和堆是所有线程共享的数据区

程序计数器

重点:

  • 是一块较小的内存空间
  • 用来选取下一条需要执行的字节码指令
  • 保证线程切换后能恢复到正确的执行位置
  • 每个线程都有一个独立的计数器
  • 线程私有

Tips:如果执行的Java方法,计数器记录的是虚拟机字节码指令的地址,如果是native方法,计数器的值为空(Undefined)

虚拟机栈(VM Stack)

重点:

  • 线程创建会同步创建Stack Frame(存储局部变量表[基本数据类型、对象引用])
  • 方法的调用和执行对应栈帧再虚拟机栈中入栈和出栈的过程

这个内存区域内规定的两类异常状况:

  • StackOverflowError(栈深度溢出)

    我的理解:一个线程里面有若干的方法,JVM会为每一个方法都会创建一个栈帧,一旦栈帧的深度超过了虚拟机栈规定的栈深度,就会产生StackOverflowError,例如递归,一个递归方法如果没有出口条件,那么会无限的调用自身,导致栈的深度过载。

  • OutofMenoryError(栈扩展失败)

    我的理解:假设栈帧里面的方法是死循环,导致栈帧耗光了JVM栈的容量,此时产生OOM异常。

本地方法栈(类似VM Stack)

Java堆

重点:

  • 线程共享
  • 存放对象实例(包括数组)
  • 垃圾收集器管理的区域(分代收集理论)
  • 分配缓冲区(Thread Local Allocation Buffer,TLAB 提升对象分配时的效率)
  • 不要求物理上连续的内存空间
  • 可扩展(通过参数-Xmx和-Xms设定)

这个内存区域可能产生的异常状况:

OutofMenoryError

**产生原因:**Java堆中没有内存完成实例分配

方法区

重点:

  • 线程共享

  • 存储类型信息、变量、静态变量、代码缓存、字符串常量池

  • 永久代/本地内存的问题

  • 垃圾回收(类卸载、常量池的回收)

  • 运行时常量池

运行时常量池

  • 存储编译产生的字面量和符号引用,在类加载后将这些数据存放到运行时常量池

直接内存(不了解)

总结

掌握java内存区域布局,以及每一块的作用,知道每个内存区域时干什么的