java虚拟机运行时数据区域

Posted Android和Java技术交流

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java虚拟机运行时数据区域相关的知识,希望对你有一定的参考价值。

在java虚拟机规范中定义了若干种程序运行期存储不同类型数据的区域。有些区域是全局共享的,随着虚拟机的创建而创建随着虚拟机的销毁而销毁。有一些区域是线程私有的,随着线程的创建而创建,随着线程的销毁而销毁。具体如下面这张图(来自网络): 

一、程序计数器

  • 1、线程私有

  • 2、一块较小的内存空间, 作用是当前线程所执行字节码的行号指示器(类似于传统CPU模型中的PC),。通俗的讲,可以将它理解成一个指针,指着当前程序(字节码文件)所运行的那一行代码。

  • 4、此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域

二、java虚拟机栈

  • 1、线程私有,生命周期与线程相同

  • 2、java虚拟机栈描述的是java方法执行时的内存概念模型,每个方法在执行的时候,都会创建一个栈帧,用来创建这个方法的操作数栈,局部变量表,方法出口,动态链接等信息,每一个方法在调用和结束的过程,就代表一个栈帧在虚拟机中入栈和出栈的过程。java虚拟机栈是一个后进先出(LIFO)的栈,靠后的方法会优先完成。

  • 3、存储栈帧,支撑java方法的调用、执行和退出

  • 4、可能会出现OutOfMemoryError和StackOverFlowError异常

三、本地方法栈

  • 1、线程私有。它跟java虚拟机栈类似,只不过java虚拟机栈是为了java虚拟机执行字节码所服务的,而本地方法栈是为了虚拟机执行native方法所服务的。

  • 2、后进先出的栈

  • 3、作用是支撑Native方法的调用、执行和退出

  • 4、可能会出现OutOfMemoryError和StackOverFlowError异常。

  • 5、有一些虚拟机(如HotSpot)将java虚拟机栈和本地方法栈合并实现。

1、下面说下java虚拟机栈帧的概念和特征。

  • 1、java虚拟机中存储的内容,他被用于存储数据和部分过程结果的数据结构,同时也被用来处理动态链接、方法返回值和异常分派。

  • 2、一个完整的栈帧包含:局部变量表、操作数栈、动态链接信息、方法正常完成和异常完成信息。

  • 3、 在编译程序代码的时候,栈帧需要多大的局部变量表,需要多深的操作数栈,这些都在编译期已经完成。java虚拟机编译期在编译的时候就把这些信息写入到class字节码文件的code表中。因此一个栈帧需要多大的内存是不会受运行期程序变量的影响的,而仅仅取决于具体的java虚拟机。

在一个线程里面,方法调用的调用链可能会很长,很多方法都处于执行的状态,对于执行引擎而言,在活动线程之中,只有位于java虚拟机栈的栈顶的那个栈帧才是有效的,这个栈帧被成为当前栈帧,与这个栈帧相关联的方法,被称为当前方法,虚拟机执行引擎中所有执行的字节码指令都针对当前栈帧和当前方法进行操作。

2、局部变量表的概念和特征

  • 1、 由若干个slot组成,长度由编译期决定

  • 2、单个slot可以存储一个类型为boolean、byte、char、short、float、reference和returnAddress的数据,两个slot可以存储一个类型为long或者double的数据。

  • 3、局部变量表用于方法见参数传递,以及方法执行过程中存储基础数据类型的值和对象的引用。

3、操作数栈的概念和特征

  • 1、是一个后进先出栈,有若干个Entry组成,长度由编译期决定

  • 2、单个Entry即可以存储一个java虚拟机中定义的任意数据类型的值,包括long和double类型,但是存储long和double类型的Entry深度为2,其他类型的深度为1

  • 3、在方法执行过程中,栈帧用于存储计算参数和计算结果;在方法调用时,操作数栈也用来准备调用方法的参数以及接受方法返回结果

四、java堆

  • 1、全局共享

  • 2、通常是java虚拟机中最大的一块内存区域,

  • 3、作用是作为java对象的主要存储区域

  • 4、JVMS明确要求改区域需要实现自动内存管理,即通常说的GC,但并限制采用哪种算法和技术去实现。

  • 5、可能出现OutOfMemoryError异常

五、方法区

  • 1、全局共享

  • 2、作用是存储java虚拟机加载到方法区之中的java类的结构信息。如之前讲的类的实例数据和类的类型数据。类的实例数据是指类中各种定义的实例对象以及它们的值;类的类型数据定义在java代码中的常量、静态变量、以及我们在类中申明的各种方法、字段等等,还会包括即时编译器编译之后产生的代码数据。

  • 3、JVMS不要求改区域实现自动内存管理,但是商用Java虚拟机能够自动管理该区域的内存

  • 4、可能出现OutOfMemoryError异常

1、运行时常量池
  • 1、全局共享

  • 2、是方法去的一部分

  • 3、作用是存储Java类文件常量池中的符号信息。

  • 4、可能出现OutOfMemoryError异常

六、直接内存

直接内存并不是jvm运行时内存区域的一部分,也不是java虚拟机规范中定义的内存区域,但是这部分内存使用的也比较频繁。特征如下:

  • 1、全局共享

  • 2、并非JVMS定义的标准java运行时内存区域

  • 3、能被自动管理,但是在检测手段上可能会有一些简陋

  • 4、随JDK1.4中加入的NIO被引入,目的是避免在java堆和Native堆中来回赋值数据带来的性能损耗

  • 5、可能出现OutOfMemoryError异常

七、java堆和栈是怎么配合工作的?

我们看上面那张图,一句嘴简单的代码为例。 
先说那行代码左边:对于编译器而言,它定义了一个 obj 的局部变量,此时在java虚拟机栈的本地变量表中必须要有一个slot去容纳这个 obj 对象所代表的的引用,所以那一行代码左边的部分对编译器的影响是它在虚拟机栈的本地变量表中预留了一个slot。

那行代码右边,也就是new Object():当代码执行到那的时候,会在java堆中产生一个Object对象,并且会把Object对象的reference赋值给java虚拟机栈的本地变量表中的obj对象所对应的变量槽之中,这个变量槽必须存储的是一个reference类型的数据。

一个reference类型的数据,它至少能完成两件事情:第一件事情是通过这个reference间接或者直接的查找到这个对象的实例数据,第二件事情是通过这个reference间接或者直接的查找到这个对象的类型数据。

直接使用指针来访问对象,最大的好处就是速度会更快。


以上是关于java虚拟机运行时数据区域的主要内容,如果未能解决你的问题,请参考以下文章

Java虚拟机运行时数据区

Java虚拟机运行时数据区域划分

Java虚拟机运行时数据区

带你了解什么是Java虚拟机运行时数据区

Java虚拟机2:Java 运行时数据区

JAVA虚拟机理解