**Java 虚拟机(Java Virtual Machine,JVM)**进程在启动时会向操作系统申请一大块堆内存空间,作为自己运行时的数据存储区域。JVM 在运行 Java 程序的过程中又会把它所管理的内存空间划分为若干个不同的数据区域(在称呼这些数据区域时常常有人以 Java 开头,用于区分操作系统中同名的内存区域,如 Java 栈、Java 堆等)。

JVM 内存布局规定了这些数据区域的申请、分配和管理的策略,保证 JVM 稳定的、高效的运行。不同的 JVM 实现对于内存的划分和管理机制也存在部分差异(对于 HotSpot VM 中的内存划分差异,主要是指方法区)。

Java虚拟机运行时数据区

Java虚拟机运行时数据区

这些区域都有各自的生命周期和用途,有的随着 JVM 进程的启动而一直存在,有的则是依赖 Java 程序中用户线程的启动和结束而建立和销毁:

JVM 内存与操作系统内存之间的关系:

1. 程序计数器

程序计数器(Program Counter Register,PC Register,PC 寄存器,PC 计数器)虽然名称源于 CPU 中的 PC 寄存器,在功能和作用上也相似,但它们并不是同一个东西。操作系统的 PC 寄存器,是与内存条一样的、位于计算机上的存储硬件,只不过 PC 寄存器位于 CPU 内,而内存是外挂在 CPU 的数据总线上。JVM 中的 PC 寄存器位于由 JVM 向操作系统申请的堆中,是对物理 PC 寄存器的一种抽象模拟。实际上在 JVM 概念模型中,还抽象了许多计算机系统的底层思想,例如 JVM 也有自己的堆、自己的栈、自己的 PC 寄存器等等。

<aside> 💡 JVM 概念模型:是指根据《Java虚拟机规范》实现的所有 JVM 的统一「外观」,但各款具体的 JVM 实现并不一定要完全按照规范中的概念模型来设计,可能部分实现会通过更高效率的等价方式去代替它。

</aside>

《Java虚拟机规范》中有说明,每个线程都有着它自己的程序计数器,并且是线程私有的,每个线程中的程序计数器是互不影响、独立存储的。显然程序计数器的生命周期与当前线程的生命周期保持一致:每个线程在启动时,就有一个与之对应的程序计数器被 JVM 建立,并在线程结束时销毁。

程序计数器相较于其他的运行时数据存储区域只是一块很小的内存空间,小到几乎可以忽略不计的程度,并且也是运行速度最快的存储区域。它是用于记录正在执行的虚拟机字节码指令的地址(可以看作是正在执行的指令代码),执行引擎就能读取程序计数器的值来决定执行何种指令。

前提是该线程正在执行的是 Java 方法。如果正在执行的是本地(Native)方法,则这个程序计数器的值为空(Undefined)。因为程序计数器只记录字节码指令地址,本地方法一般由 C/C++ 或其他语言实现,不存在字节码指令。

程序计数器是唯一一个在《Java虚拟机规范》中没有规定任何 OutOfMemoryError 情况的区域。