Java的运行时数据区

来源:互联网 发布:数据库方案 编辑:程序博客网 时间:2024/05/23 18:42

Java的运行时数据区


Java虚拟机定义了若干中程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。同样也有一些则是与线程一一对应的内存区域,这些与线程对应的数据区域会随着线程开始和结束被创建和销毁。大致可以将Java运行时内存区域分为两类:虚拟机托管所有线程共享内存区域以及线程私有的内存区域,如下图所示:

Java HotSpot JVM


PC寄存器(Program Counter Register)

Java虚拟机可以允许多条线程同时执行,每条JVM线程都有自己的PC寄存器。在任意时刻,一条JVM线程只会执行一个方法的代码路径,该方法称为该线程的当前方法(Current Method).如果该方法不是native的,则PC寄存器就保存了JVM正在执行的字节码指令的地址;否则,PC寄存器的值时undefined。 PC寄存器的容量至少应该能够保存一个returnAddress类型的数据或者一个与平台相关的本地指针的值。

Java虚拟机栈(Java Virtual Machine Stack, JVM Stack)

每条JVM线程都有自己私有的Java虚拟机栈(Java Virtual Machine Stack),这个栈随着线程创建和销毁,用于存储栈帧(Frame)。 JVM Stack的作用与传统语言,如C语言,中的栈十分类似,用于存储局部变量和中间结果的内存区域。

Java堆(Java Heap)

JVM中,堆(heap)是提供各种线程共享的运行时内存区域,也是供所有类实例和数组对象分配内存的区域。Java堆在JVM启动时被创建,存储了被自动内存管理系统(Automatic Storage Management System,也即是 Gargabe Collector 垃圾收集器)管理的各种对象,这里的对象无需,也无法被显式销毁。

方法区(Method Area)

JVM中,方法区时可供各个线程共享的运行时内存区域。方法区与传统语言中的编译代码存储区(Storage Area of Compiled Code)或者操作系统进程的正文段(Text Segment)的作用十分相似,其存储了每个类的结构信息、字段和方法数据、构造方法和普通方法的字节码内容,还包括一些在类、实例、接口初始化时用到的特殊方法,另外,运行时常量池(Runtime Constant Pool)也保存在这里.方法区在JVM启动时被创建,在逻辑上时堆的一部分。同时,其实际内存空间可以不连续。

运行时常量池(Runtime Constant Pool)

运行时常量池是每个类或接口的常量池(Constant Pool)的运行时表现形式,它包括了多种不同的常量:编译时期可知的数值字面量、运行期解析获得的方法或者字段引用。运行时常量池类似于传统语言中符号表(Symbol Table)的角色。每个运行时常量池都被分配在JVM方法区中,在类和接口被加载到虚拟机后,对应的运行时常量池就会被创建(每个类都有自己的运行时常量池)。

本地方法栈(Native Method Stack)

Java 虚拟机实现可能会使用到传统的栈(通常称之为“ C Stacks”)来支持native方法( 指使用 Java 以外的其他语言编写的方法)的执行,这个栈就是本地方法栈( Native Method Stack)。当Java 虚拟机使用其他语言(例如 C 语言)来实现指令集解释器时,也会使用到本地方法栈。如果 Java 虚拟机不支持 natvie 方法,并且自己也不依赖传统栈的话,可以无需支持本地方法栈,如果支持本地方法栈,那这个栈一般会在线程创建的时候按线程分配。


栈帧(Frame)

栈帧( Frame)是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、方法返回值和异常分派( Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。栈帧的存储空间分配在Java虚拟机栈之中,每一个栈帧都有自己的局部变量表(Local Variables)、操作数栈( Operand Stack)和指向当前方法所属的类的运行时常量池的引用。局部变量表和操作数栈的容量是在编译期确定,并通过方法的Code属性保存及提供给栈帧使用。因此,栈帧容量的大小仅仅取决于 Java虚拟机的实现和方法调用时可被分配的内存。在一条线程之中,只有目前正在执行的那个方法的栈帧是活动的。这个栈帧就被称为是当前栈帧( Current Frame),这个栈帧对应的方法就被称为是当前方法( Current Method),定义这个方法的类就称作当前类( Current Class)。对局部变量表和操作数栈的各种操作,通常都指的是对当前栈帧的对局部变量表和操作数栈进行的操作。如果当前方法调用了其他方法,或者当前方法执行结束,那这个方法的栈帧就不再是当前栈帧了。当一个新的方法被调用,一个新的栈帧也会随之而创建,并且随着程序控制权移交到新的方法而成为新的当前栈帧。当方法返回的之际,当前栈帧会传回此方法的执行结果给前一个栈帧,在方法返回之后,当前栈帧就随之被丢弃,前一个栈帧就重新成为当前栈帧了。栈帧是线程本地私有的数据,不可能在一个栈帧之中引用另外一条线程的栈帧。

有些地方理解的不是很透彻,以后加以补充

0 0
原创粉丝点击