1. 程序计数器(线程私有)Program Counter Register

  • 1)可以看作当前线程所执行的字节码的行号指示器;
  • 2)Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各个线程之间计数器互不影响,独立存储;
  • 3)此区域不存在OutOfMemoryError的异常

2. Java虚拟机栈(线程私有)Java Virtual machine Stacks

  • 1)生命周期和线程相同
  • 2)虚拟机栈描述的是Java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用直至执行完成的过程,对应着一个栈帧在虚拟机中入栈到出栈的过程
  • 3)平常所说的堆、栈,这个栈指的是:虚拟机中局部变量表部分
  • 4)局部变量表存放编译期间的各种基本数据类型(boolean、byte、char、short、int、float、long、double)、对象引用(reference类型)和returnAddress类型(指向了一条字节码指令的地址)
  • 5)局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法所需的栈帧分配多大的局部变量空间是完全确定的,在方法运行期间不会改变局部变量表的大小
  • 6)此区域存在两种异常:
  • 如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常;
  • 如果虚拟机在扩展栈时无法申请到足够的内存空间,就会抛出OutOfMemoryError异常。
  • 7)为虚拟机执行Java方法(即字节码)服务
  • 8)在HotSpot虚拟机中,是虚拟机栈和本地方法栈是合二为一的,栈容量由-Xss参数设置

3. 本地方法栈(线程私有) Native Method Stack

  • 1)为虚拟机使用到的Native方法服务
  • 2)此区域存在两种异常:
  • 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
  • 如果虚拟机栈动态扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常

4. Java堆(线程共享)Java Heap

  • 1)在虚拟机启动时创建
  • 2)所有的对象实例、数组都在堆上分配
  • 3)可通过-Xmx(堆的最大值)和-Xms(堆的最小值)来控制虚拟机堆的大小;
  • 4)将-Xmx和-Xms参数值设置为一样,即可避免堆自动扩展
  • 5)如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,就会抛出OutOfMemoryError异常
  • 6)通过参数-XX:+HeapDumpOnOutOfMemoryError可让虚拟机在出现内存溢出异常时Dump当前的内存堆转储快照以便后续分析

5. 方法区(线程共享)Method Area

  • 1)用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
  • 2)当方法区无法满足内存分配需求时,将会抛出OutOfMemoryError异常
  • 3)通过-XX:PermSize(最小方法区容量)和-XX:MaxPermSize(最大方法区容量)限制方法区大小,从而间接限制其中常量池的大小

6. 运行时常量池(Runtime Constant Pool)

  • 1)是方法区的一部分
  • 2)Class文件中的常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放
  • 3)除了保存Class文件中描述的符号引用外,还会把翻译出来的直接引用也存储到运行时常量池中
  • 4)是方法区的一部分,也受到方法区内存的限制,当常量池无法再申请到内存时,将会抛出OutOfMemoryError异常

7. 直接内存(Direct Memory)

  • 1)本机直接内存不会受到Java堆大小的限制,但是会受到本级总内存大小以及处理器寻址空间的限制
  • 2)也会出现OutOfMemoryError异常
  • 3)直接内存容量可以通过-XX:MaxDirectMemorySize指定,如果不指定,则默认与Java堆最大值(-Xmx指定)一样