JVM之运行时数据区(Runtime Data Area)

JVM之运行时数据区(Runtime Data Area)

这里主要以JDK8之后的JVM内存布局为介绍重点,首先看一张图
在这里插入图片描述

从图中可以看出运行时数据区主要分为以下几部分:

1.程序计数器:
2.本地方法栈:
3.虚拟机栈
4.堆区
5.元空间(永久代)

这几部分中有线程共享的和单独线程私有的。即

1.独立线程私有:包括程序计数器、虚拟机栈、本地方法栈
2.线程间共享:堆区、堆外内存(永久代或者元空间、代码缓存)
程序计数器

一块很小的内存空间,几乎可以忽略

生命周期以线程的生命周期保持一致。

并非是物理寄存器,JVM是对物理PCR的一种模拟。

作用:用来存储指向下一条指令的地址,由执行引擎读取下一条指令

虚拟机栈(Java栈)

1.每个线程创建时都会创建一个虚拟机栈,内部保存一个个的栈帧,一个栈帧对应一个方法

2.生命周期与线程的生命周期保持一致。

3.作用:负责Java程序的运行,保存方法的局部变量,部分结果。参与方法的调用和返回。

JVM对虚拟机栈的操作只有两个:

​ 1.每个方法的执行,伴随着入栈操作

​ 2.方法执行结束后的出栈操作

栈帧的内部结构

每个栈帧中存储以下:

1.局部变量表(Local Variables)
2.操作数栈(Operand Stack)(或表达式栈)
3.动态链接(Dynamic Linking)
4.方法返回地址(Return Address)
5.一些附加信息

在这里插入图片描述
局部变量表(局部变量数组或本地变量表)

1.定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量

2.局部变量表中的变量只在当前方法中调用有效,当方法调用结束后,随着栈帧的销毁,局部变量表也随之销毁。

在方法体内的局部变量

2.局部变量表中的变量只在当前方法中调用有效,当方法调用结束后,随着栈帧的销毁,局部变量表也随之销毁。

操作数栈(Operand Stack)

1.主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间

2.在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈和出栈

3.如果被调用的方法带有返回值的话,其返回值会被压入当前栈的操作数栈中。并且会更新PC寄存器中下一条需要执行的字节码指令

下面举个简单的例子吧。

首先是代码举例
在这里插入图片描述

首先看下这个栈帧中的局部变量表吧
在这里插入图片描述
其对应的字节码指令信息如下:

在这里插入图片描述
下面是字节码指令信息解释:

1.bipush: Push byte 
2.istore: Store int into local variable
3.iload: Load int from local variable
4.iadd: Add int
5.getstatic:  Get static field from class
6.invokevirtual: Invoke instance method; dispatch based on class  编译期间不能确定的方法
7.return: Return void from method

扩充点其他的知识

方法的调用:虚方法和非虚方法

非虚方法:如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的。这样的方法就称为非虚方法。

非虚方法包括:静态方法、私有方法、final方法,实例构造器、父类方法

其他方法称为虚方法。

虚拟机中提供了几条方法调用指令

1.普通调用指令:

​ invokestatic:调用静态方法,解析阶段确定唯一方法的版本。

​ invokespecial:调用私有和父类方法,解析阶段确定唯一方法版本

​ invokevirtual: 调用所有虚方法

​ invokeinterface:调用接口方法

2.动态调用指令

​ invokedynamic:动态解析出需要调用的方法,然后执行。

动态链接(指向运行时常量池的方法引用)

在Java源文件编译成字节码文件时,所有的变量和方法引用会作为符号引用保存在class文件的常量池里。动态链接的作用将这些符号引用转换为调用方法的直接引用,

这里可以理解为引用方法区里运行时常量池的各种引用。

方法返回地址

存放调用该方法的PC寄存器的值。

方法正常退出时,调用者的PC寄存器的值作为返回地址返回给执行引擎,执行引擎然后开始执行下一条指令。即调用该方法的指令的下一条指令的地址

异常退出的,返回地址通过异常表现来确定,栈帧中不会保存这部分信息。

一些附加信息

可选部分,会携带比如对程序调试提供支持的附加信息。

本地方法栈(Native Method Stack)

​ Java虚拟机栈用来管理Java方法的调用,而本地方法栈用于管理本地方法的调用

​ Java虚拟机栈为虚拟机执行 Java 方法(也就是字节码)服务,而本地方法栈则是为虚拟机使用到的 Native 方法服务。

​ 虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。

Navtive 方法是 Java 通过本地方法接口(JNI) 直接调用本地 C/C++ 库,可以认为是 Native 方法相当于 C/C++ 暴露给 Java 的一个接口,Java 通过调用这个接口从而调用到 C/C++ 方法。

本地方法接口的简单理解

本地方法:简单理解一个本地方法就是一个Java方法调用非Java代码的接口。该方法的实现由非Java语言实现。

定义一个本地方法时,不提供实现体。下面是一些本地方法举例。

在这里插入图片描述
本地接口的作用是融合其他的编程语言为Java语言使用。主要为C/C++语言。

使用Native Method的原因?

1.与Java环境外交互:Java应用需要与Java外面的环境交互,这是本地方法的主要原因。

2.与操作系统交互:通过使用本地方法,得以用Java实现jre的与底层系统的交互,

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页