1、程序计数器
线程私有。是一块较小的内存,是当前线程所执行的字节码的行号指示器。是Java虚拟机规范中唯一没有规定OOM(OutOfMemoryError)的区域。如果线程执行的是非native方法,则程序计数器中保存的是当前需要执行的指令的地址;如果线程执行的是native方法,则程序计数器中的值是undefined。
2、Java 栈( Java 虚拟机栈)
线程私有。java栈和线程的生命周期相同。是Java方法执行的内存模型。java栈中存放的是一个个栈帧,执行每个方法都会创建一个栈帧,用于存储局部变量,操作数(对象引用),指向运行时常量池的引用,发放返回值地址和附加信息。局部变量所需要的内存空间大小在编译期间完成分配。所以栈帧的大小不会改变。存在两种异常情况:若线程请求深度大于栈的深度,抛StackOverflowError。若栈在动态扩展时无法请求足够内存,抛OOM。
3、本地方法栈
线程私有。与Java栈类似,但是不是为Java方法(字节码)服务,而是为本地非Java方法服务。也会抛StackOverflowError和OOM。
4、Java 堆
所有线程共享。虚拟机启动时创建。存放对象实例和数组。所占内存最大。分为新生代(Young区),老年代(Old区)。新生代分Eden区,Servior区。Servior区又分为From space区和To Space区。Eden区和Servior区的内存比为8:1。 当扩展内存大于可用内存,抛OOM。
5、方法区(非堆)
所有线程共享。用于存储已被虚拟机加载的类信息(包括类的名称、方法信息、字段信息)、常量、静态变量等数据。又称为非堆(Non – Heap)。方法区又称“永久代”。GC很少在这个区域进行,但不代表不会回收。这个区域回收目标主要是针对常量池的回收和对类型的卸载。当内存申请大于实际可用内存,抛OOM。