Jvm运行时数据区有哪些

程序计数器(Program Counter Register)
- 作用: 
- 可以看作是当前线程所执行的字节码的行号指示器。
 - 在多线程环境下,每个线程都有自己独立的程序计数器,线程私有的,用于记录该线程正在执行的字节码指令地址,以便线程切换后能恢复到正确的执行位置。
 - 用来存储指向下一条指令的地址:即将执行的指令代码
 
 - 特点: 
- 是一块较小的内存空间。
 - 如果线程正在执行的是一个 Java 方法,程序计数器记录的是正在执行的虚拟机字节码指令的地址;
 - 如果正在执行的是 Native 方法,这个计数器值则为空(Undefined)。
 
 
Java 虚拟机栈(Java Virtual Machine Stacks)
- 作用: 
- 用于存储方法调用的栈帧(Stack Frame)。
 - 每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法返回地址等信息。 
- 局部变量表:存放了编译期可知的各种基本数据类型(
boolean、byte、char、short、int、float、long、double)、对象引用(reference类型)和returnAddress类型(指向了一条字节码指令的地址) 
 - 局部变量表:存放了编译期可知的各种基本数据类型(
 
 - 特点: 
- 线程私有,与线程的生命周期相同,每个线程都有自己独立的虚拟机栈。
 - 栈的大小可以固定也可以动态扩展。 
- 栈的深度超出了允许的范围:抛出 
StackOverflowError异常; - 栈可以动态扩展但在扩展时无法申请到足够的内存空间:抛出 
OutOfMemoryError异常。 
 - 栈的深度超出了允许的范围:抛出 
 
 
本地方法栈(Native Method Stacks)
- 作用: 
- 与虚拟机栈类似,但是用于**支持本地方法(Native Method)**的执行。 
- 本地方法:用其他语言(如 C、C++)实现的方法,在 Java 中可以通过
native关键字声明。 
 - 本地方法:用其他语言(如 C、C++)实现的方法,在 Java 中可以通过
 
 - 与虚拟机栈类似,但是用于**支持本地方法(Native Method)**的执行。 
 - 特点: 
- 线程私有。
 - 其具体实现方式和行为可能因不同的 JVM 实现而有所差异。
 - 如果本地方法栈的深度超出限制 / 在扩展时无法申请到足够内存,也会抛出 
StackOverflowError或OutOfMemoryError异常。 
 
Java 堆(Java Heap)
- 作用: 
- 用于存储对象实例和数组。
 - 几乎所有的对象实例都在堆上分配内存。
 - 堆是垃圾回收的主要区域(GC堆),JVM 会自动管理堆内存,回收不再使用的对象,以避免内存泄漏。
 
 - 特点: 
- 线程共享,所有线程都可以访问堆中的对象。
 - 堆的大小可以通过参数进行调整。 
- 如果堆内存不足,会抛出 
OutOfMemoryError异常。 
 - 如果堆内存不足,会抛出 
 
 
方法区(Method Area)
- 作用: 
- 存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
 
 - 特点: 
- 线程共享
 - 在 Java 8 之前,方法区被称为永久代(Permanent Generation);
 - 从 Java 8 开始,使用元空间(Metaspace)来替代永久代 
- 元空间使用本地内存,而不是 JVM 堆内存。
 - 方法区无法满足内存分配需求:抛出 
OutOfMemoryError异常。 
 
 
运行时常量池(Runtime Constant Pool)
- 是方法区的一部分。
 - 用于存放编译期生成的各种字面量和符号引用,在类加载后进入方法区的运行时常量池中存放。
 - 运行时常量池相对于Class文件常量池的一个重要特征是具备动态性,运行期间也可能将新的常量放入池中。