总是记不住这几个运行时数据区,还是再捋一遍吧。
常见分类,一共5个区域,分为2种类型:
- 线程共享
- 方法区 Method Area
- 堆内存 Heap
- 线程独享
- 虚拟机栈 VM Stack
- 本地方法栈 Native Method Stack
- 程序计数器 Program Counter Register
1.方法区
存储已被虚拟机加载的类型信息、常量、静态变量、即时编译后的代码缓存等数据。
JDK6时,计划放弃永久代,逐步改为本地内存来实现方法区的计划;
JDK7,把原本放在永久代的字符串常量池、静态变量等移出;
JDK8,完全废弃永久代的概念,改用在本地内存中实现的元空间Meta-space来代替,把JDK7遗留的(主要是类型信息)全部移到元空间中。
2.堆内存
G1收集器出现为分界,之前,业界绝对主流的Hotspot虚拟机,内部垃圾收集器全部都基于“经典分代”来设计,需要新生代、老年代收集器搭配才能工作;之后,Hotspot虚拟机里也出现了不采用分代设计的新垃圾收集器。
所有线程共享的Java堆中,可以划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer, TLAB),以提升对象分配时的效率。
3.虚拟机栈 Java Virtual Machine Stack

为虚拟机执行Java方法(字节码)服务。
线程私有,生命周期与线程相同。
线程栈由多个栈帧(Stack Frame)组成。
栈帧用于存储局部变量表、操作数栈、动态连接、方法出口、附加信息等。
两类异常:
- 线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError异常;
- Java虚拟机栈容量可以动态扩展,当栈扩展时无法申请到足够的内存会抛出OutOfMemoryError异常。
4.本地方法栈 Native Method Stacks
为虚拟机使用到的本地(Native)方法服务。
线程私有,生命周期与线程相同。
Hotspot虚拟机直接把本地方法栈和虚拟机栈合二为一。
StackOverflowError异常和OutOfMemoryError异常。
5.程序计数器 Program Counter Register
程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖程序计数器来完成。
Java虚拟机多线程实现方式:通过线程轮流切换、分配处理器执行时间。
线程执行的Java方法,计数器记录的是正在执行的虚拟机字节码指令的地址。
线程执行的本地方法,计数器值为空(Undefined)。
此内存区域是唯一一个在规范中没有规定任何OutOfMemoryError情况的区域。