官网地址:Chapter 2. The Structure of the Java Virtual Machine
上一篇内容:记录了 class 文件结构,详情请看:JVM<一> 初识JVM CLASS文件结构_丛林雪狼code的博客-CSDN博客
这一篇主要讲述 jvm 的运行时区域;在此,感谢各路大神贡献的文献;
JVM 运行时区域 Run-TIme Data Areas ,官方文档上展示了6个部分:
1)The pc Register 程序计数器
Java 虚拟机可以同时支持多个执行线程。每个 Java 虚拟机线程都有自己的 pc
(程序计数器)。在任何时候,每个 Java 虚拟机线程都在执行单个方法的代码,即该线程的当前方法。如果该方法不是 native(本地方法)
,则该pc
计数器包含当前正在执行的 Java 虚拟机指令的地址。如果线程当前正在执行的方法是native
,则 Java 虚拟机pc
寄存器的值是未定义的。Java 虚拟机的pc
register 足够宽,可以returnAddress
在特定平台上保存一个或一个本地指针。
意思就是说:程序技术器是私有的内存区域;每个线程都有自己的程序计数器;JVM 可以同时执行多个线程,每个线程之间互不影响;程序计数器:实际上就是指令地址,记录当前或者下一次的指令;如果当前的方法是本地方法,则PC 是未定义的;如果正在执行的不是本地方法,则PC 记录的是此次当前的指令地址;
2)java Virtual Machine Stacks 虚拟机栈
每个 Java 虚拟机线程都有一个私有的Java 虚拟机栈,与线程同时创建。Java 虚拟机栈存储栈帧。Java 虚拟机栈类似于 C 等传统语言的栈:它保存局部变量和部分结果,并在方法调用和返回中发挥作用。因为除了推送和弹出帧之外,Java 虚拟机堆栈从不直接操作,所以帧可能被分配在堆上。Java 虚拟机堆栈的内存不需要是连续的。
3)Heap 堆
Java 虚拟机有一个在所有 Java 虚拟机线程之间共享的堆。堆是运行时数据区,从中分配所有类实例和数组的内存。堆是在虚拟机启动时创建的。对象的堆存储由自动存储管理系统(称为垃圾收集器)回收;对象永远不会被显式释放。Java 虚拟机没有假设任何特定类型的自动存储管理系统,可以根据实现者的系统需求选择存储管理技术。堆的大小可以是固定的,也可以根据计算的需要进行扩展,如果不需要更大的堆,则可以收缩。堆的内存不需要是连续的。
4)Method Area 方法区
Java 虚拟机有一个在所有 Java 虚拟机线程之间共享的方法区。方法区类似于常规语言的编译代码的存储区或类似于操作系统进程中的“文本”段。它存储每个类的结构,例如运行时常量池、字段和方法数据,以及方法和构造函数的代码,包括在类和实例初始化和接口初始化中使用的特殊方法(父类的无参构造方法)。方法区是在虚拟机启动时创建的。尽管方法区在逻辑上是堆的一部分,但简单的实现可能会选择不进行垃圾收集或压缩它。本规范不强制要求方法区的位置或用于管理编译代码的策略。方法区可以是固定大小,也可以根据计算需要进行扩展,如果不需要较大的方法区,可以进行收缩。方法区的内存不需要是连续的。
5)Run-TIme Constant Pool 运行时常量池
运行时间常数池是每个类或每个接口的运行时表示constant_pool
在表class
文件。它包含多种常量,从编译时已知的数字文字到必须在运行时解析的方法和字段引用。运行时常量池的功能类似于传统编程语言的符号表,尽管它包含的数据范围比典型的符号表更广。每个运行时常量池都是从 Java 虚拟机的方法区分配的。类或接口的运行时常量池是在Java 虚拟机创建类或接口时构造的。
6)Native Method Stacks 本地方法栈
Java 虚拟机的实现可以使用传统的堆栈,通俗地称为“C 堆栈”,以支持native
方法(用 Java 编程语言以外的语言编写的方法)。本机方法堆栈也可以由 Java 虚拟机指令集的解释器实现使用,例如 C 语言。无法加载native
方法且本身不依赖常规堆栈的Java 虚拟机实现不需要提供本地方法栈. 如果提供,则通常在创建每个线程时为每个线程分配本地方法栈。
这里来贴一张汇总的图,更加清晰的描述运行时区域
java 源代码 经 javac 编译为 class 文件(PS:咖啡宝贝 CAFEBABE) ,运行JVM ,加载class 文件 ,进行类加载,执行class 字节指令 (运行程序),JVM 启动分配 方法区、加载常量池、开辟堆内存、开启程序计数器、开起本地方法栈、虚拟机栈,这是一个简单的叙述流程;
详细叙述请看图;