程序计数器(Program Counter Register):
- 线程私有,作为当前线程的行号指示器,用于记录当前虚拟机正在执行的线程指令地址。
- 通过它实现代码的流程控制,如顺序执行、选择、循环、异常处理等。
- 是唯一一个不会出现OutOfMemoryError的内存区域,其生命周期随着线程的创建而创建,随着线程的结束而结束。
Java虚拟机栈(Java Virtual Machine Stacks,又称Java栈):
- 线程私有,由一个个栈帧(Stack Frame)组成。
- 每个栈帧中都拥有局部变量表、操作数栈、动态链接、方法出口信息等。
- 每一次函数调用都会有一个对应的栈帧被压入虚拟机栈,每一个函数调用结束后,都会有一个栈帧被弹出。
- 局部变量表用于存放方法参数和方法内的局部变量。
- 可能出现*Error和OutOfMemoryError异常。
本地方法栈(Native Method Stacks):
- 线程私有,用于支持Java调用本地方法(Native Method)。
- 与虚拟机栈的作用相似,但虚拟机栈为Java方法服务,而本地方法栈为本地方法服务。
- 也可能出现*Error和OutOfMemoryError异常。
堆(Heap Area):
- 线程共享,用于存放对象实例和数组,是Java内存管理的主要区域。
- 可以细分为新生代(包括Eden空间、From Survivor、To Survivor空间)和老年代。
- 通过-Xms参数设定程序启动时占用内存大小,通过-Xmx参数设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常。
方法区(Method Area):
- 又称为永久代(Permanent Generation,在JDK 1.8之前使用),但在JDK 1.8中已被元空间(MetaSpace)取代。
- 线程共享,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
- 在JDK 1.8之前,方法区在JVM内存中,受JVM内存大小参数限制。而在JDK 1.8及之后,元空间直接在物理(本地)内存中实现,不再受JVM内存大小参数限制,但物理内存不足时仍可能报OOM。