JVM之运行时数据区

Java虚拟机运行时数据区包括PC寄存器、Java虚拟机栈、Java堆、方法区、本地方法栈、运行时常量池六个部分。
JVM运行时数据区

1. PC寄存器

PC寄存器(又叫程序计数器,Program Counter Register),每一条Java虚拟机线程都有自己的PC寄存器。PC寄存器报错当前正在执行方法的字节码指令地址;如果当前方法是native的,则PC寄存器的值为undefined。

2. Java虚拟机栈

Java虚拟机栈(Java Virtual Machine Stack),每一条Java虚拟机线程都有自己私有的Java虚拟机栈,用于存储栈帧。

2.1 栈帧

栈帧(Frames)一种数据结构,用于存储局部变量和部分过程结果,也用于处理动态链接(Dynamic Linking)、方法返回值、异常分派(Dispatch Exception)。
栈帧随方法的调用创建,随方法的结束销毁(方法正常完成,抛出在方法内未捕获的异常都算做方法结束)。

每个栈帧拥有自己的局部变量表(Local Variables)、操作数栈(Operand Stack)和指向当前方法所属的类的运行时常量池的引用。

一个线程只有目前执行的方法的栈帧是活动的。这个栈帧就是当前栈帧,这个栈帧对应的方法就是当前方法,定义这个方法的类就是当前类。

当前栈帧正常执行完成后,还需要恢复调用者状态,包括调用者的局部变量表、操作数栈、和被正确增加过来表示执行了该方法调用指令的程序计数器等。

2.1.1 局部变量表

局部变量表(Local Variables)的长度由编译期决定,并存储在类或接口的二进制表示中--通过方法的Code属性保存并提供给栈帧使用。

一个局部变量可以保存类型为boolean、byte、char、short、float、reference和returnAddress的数据;两个局部变量可以保存类型为long、double的数据。

局部变量表通过索引访问,索引值从0开始。long或double占用两个连续的局部变量,使用较小的索引值来调用。当调用实例方法时,第一个局部变量(索引值0)用来存储被调用方法的对象引用(即this)。

2.1.2 操作数栈

操作数栈(Operand Stack)是一个后进先出(Last-In-First-Out)栈。操作数的长度由编译期决定,也存储在类或接口的二进制表示中,通过方法的Code属性保存并提供给栈帧使用。

操作数栈所属的栈帧在刚刚被创建时,操作数栈是空的。每个操作数栈的成员(Entry)可以保存一个Java虚拟机定义的任意数据类型的值,long和double也保存在一个成员中,成员是一个操作单位,但并不是一个存储单位,一个long或double类型的数据会占用两个单位的栈深度,其他数据类型占用一个。

在操作数栈中,一项运算常由多个子运算嵌套进行,一个子运算的过程的结果可以被其他外围运算使用。

2.1.3 运行时常量池的引用

每个栈帧都包含一个纸箱运行时常量池的引用,用于支持当前方法的代码实现动态链接(Dynamic Linking)。在Class文件中,描述一个方法调用了其他方法或者访问其成员变量是通过符号引用(Symbolic Reference)来表示的,动态链接的作用就是将这些符号引用所表示的方法转换为实际方法的直接引用。

3. Java堆

Java堆(Heap)是线程共享的,跟随Java虚拟机的生命周期。所有类实例和数组对象存储在堆中。

4.方法区

方法区(Method Area)是线程共享的,跟随Java虚拟机的生命周期。用于存储每一个类的结构信息,如运行时常量池、字段和方法数据、构造函数和普通方法的字节码内容、还包括一些在类、实例、接口初始化时用到的特殊方法(类或接口初始化方法<clinit>、实例初始化方法 <init>)

方法区是堆得逻辑组成部分,但是虚拟机可以不对这个区域进行垃圾回收(GC)。

5.运行时常量池

运行时常量池(Runtime Constant Pool)是每一个类或接口的常量池(Constant_Pool) [1],常量池保存了数值字面量、方法或字段的符号引用等。

每一个运行时常量池都分配在Java虚拟机的方法区中,在类或接口被加载到虚拟机后,对应的运行时常量池就被创建出来。

6.本地方法栈

本地方法栈(Native Method Stack)用来支持native方法的执行。和Java虚拟机栈类似也是跟随线程的生命周期。


  1. 常量池待详细整理

posted @ 2016-07-15 11:41  Rhys  阅读(609)  评论(0编辑  收藏  举报