JVM 的运行时数据区

JVM(Java Virtual Machine)的运行时数据区(Runtime Data Areas)是指在JVM运行过程中,用于管理和存储程序数据的内存区域。这些内存区域在JVM启动时分配,并在JVM关闭时释放。根据《Java虚拟机规范》,运行时数据区可以划分为以下几个部分:

1. 程序计数器(Program Counter Register)

程序计数器是一个小内存区域,每个线程都有自己的程序计数器。它用于存储当前正在执行的字节码指令的地址。如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的字节码指令的地址;如果正在执行的是本地方法(native method),这个计数器值则为空(Undefined)。

2. Java虚拟机栈(Java Virtual Machine Stack)

Java虚拟机栈是线程私有的,每个线程都有一个自己的Java虚拟机栈。它存储着线程的状态信息,包括方法调用和执行的相关数据。每个方法被调用时,都会在Java虚拟机栈中创建一个栈帧(Stack Frame),用于存储局部变量、操作数栈、动态链接、方法出口等信息。当方法执行完毕,栈帧会被销毁。

栈帧(Stack Frame)

每个栈帧包括:

  • 局部变量表(Local Variable Table):存储方法的局部变量,包括基本数据类型、对象引用和returnAddress类型。
  • 操作数栈(Operand Stack):用于存储计算过程中的中间结果,并作为方法调用和返回时的参数传递。
  • 动态链接(Dynamic Linking):每个栈帧包含一个指向运行时常量池的方法引用,支持当前方法的动态链接。
  • 方法返回地址(Return Address):当方法调用完成后,需要返回到调用方法的位置。

3. 本地方法栈(Native Method Stack)

本地方法栈与Java虚拟机栈类似,但它是为本地方法服务的。每当一个本地方法被调用时,就会在本地方法栈中创建一个栈帧。它主要用于处理通过JNI(Java Native Interface)调用的C/C++代码。

4. 堆(Heap)

堆是JVM内存中最大的一块区域,所有的对象实例和数组都在堆中分配内存。堆是所有线程共享的内存区域。根据垃圾回收机制的需要,堆可以进一步细分为新生代(Young Generation)和老年代(Old Generation)。

新生代(Young Generation)

新生代存储生命周期较短的对象。新生代又分为三个区域:

  • 伊甸区(Eden Space):新创建的对象首先分配在伊甸区。
  • 幸存者区0(Survivor Space 0):从伊甸区复制过来的存活对象。
  • 幸存者区1(Survivor Space 1):从幸存者区0复制过来的存活对象。

老年代(Old Generation)

老年代存储生命周期较长的对象。当对象在新生代经过多次垃圾回收仍然存活时,会被移动到老年代。

5. 方法区(Method Area)

方法区是一个共享内存区域,用于存储已被JVM加载的类信息、常量、静态变量、即时编译后的代码等数据。方法区可以看作是堆的一个逻辑部分。不同于堆,方法区的垃圾回收频率较低。

6. 运行时常量池(Runtime Constant Pool)

运行时常量池是方法区的一部分,用于存储编译时生成的各种字面量和符号引用。运行时常量池在类加载后创建,包含类的各种信息,比如类名、字段名、方法名以及对应的描述符等。

7. 直接内存(Direct Memory)

直接内存并不是JVM规范中明确规定的内存区域,但它确实被广泛使用。直接内存是在JVM之外,由操作系统直接分配的内存,通过java.nio包中的ByteBuffer类来操作。直接内存的分配不受堆大小的限制,但受制于操作系统的内存大小。

运行时数据区的图示

sql 复制代码
--------------------------------
|         堆(Heap)           |
|   -------------------------  |
|  |       新生代(Young)    | |
|  |  ---------------------   | |
|  | | 伊甸区   | 幸存者区0  | | |
|  | | (Eden)  | (S0)       | | |
|  | |         |            | | |
|  |  ---------------------   | |
|  |  ---------------------   | |
|  | | 幸存者区1           | | |
|  | | (S1)               | | |
|  |  ---------------------   | |
|   -------------------------  |
|   -------------------------  |
|  |        老年代(Old)     | |
|  |                         | |
|   -------------------------  |
--------------------------------
|        方法区(Method Area)  |
|   -------------------------  |
|  |   运行时常量池(RCP)    | |
|   -------------------------  |
--------------------------------
|      程序计数器(PC Register)|
--------------------------------
|   Java虚拟机栈(JVM Stack)   |
|   -------------------------  |
|  |    栈帧(Stack Frame)    | |
|  |  ---------------------   | |
|  | | 局部变量表           | | |
|  | | 操作数栈             | | |
|  | | 动态链接             | | |
|  | | 方法返回地址         | | |
|  |  ---------------------   | |
|   -------------------------  |
--------------------------------
|    本地方法栈(Native Stack) |
--------------------------------

总结

JVM的运行时数据区是支持Java程序执行的关键组成部分。每个区域都有其特定的用途和特点,这些区域共同工作,支持Java程序的运行和内存管理。理解这些数据区的功能和相互关系,对于优化Java应用程序性能和解决内存问题具有重要意义。

相关推荐
coooliang33 分钟前
【Android】ViewPager的使用
android
xvch3 小时前
Kotlin 2.1.0 入门教程(二十五)类型擦除
android·kotlin
李长渊哦7 小时前
常用的 JVM 参数:配置与优化指南
java·jvm
数巨小码人10 小时前
QT SQL框架及QSqlDatabase类
jvm·sql·qt
simplepeng11 小时前
我的天,我真是和androidx的字体加载杠上了
android
小猫猫猫◍˃ᵕ˂◍12 小时前
备忘录模式:快速恢复原始数据
android·java·备忘录模式
CYRUS_STUDIO14 小时前
使用 AndroidNativeEmu 调用 JNI 函数
android·逆向·汇编语言
梦否14 小时前
【Android】类加载器&热修复-随记
android
徒步青云15 小时前
Java内存模型
android
今阳15 小时前
鸿蒙开发笔记-6-装饰器之@Require装饰器,@Reusable装饰器
android·app·harmonyos