JVM虚拟机系统性学习-运行时数据区(虚拟机栈、本地方法栈)

虚拟机栈

虚拟机栈为每个线程所私有的,如下图:

栈帧是什么?

栈帧存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息

栈内存为线程私有的空间,每个方法在执行时都会创建一个栈帧,执行该方法时,就会将该方法所对应的栈帧入栈

  • 局部变量表:用于存储方法参数和定义在方法体内部的局部变量,局部变量表的容量在编译器就被确定下来

  • 操作数栈:在方法执行过程中,根据字节码指令,往栈中写入数据或者提取数据,即入栈、出栈

  • 动态链接:每一个栈帧内部都包含一个指向 运行时常量池 中该栈所属方法的引用,包含这个引用的目的就是为了支持当前方法的代码能够实现动态链接,在 Java 源代码被编译为字节码文件时,所有变量和方法都为符号引用保存在 class 文件的常量池,动态链接的作用就是将这些符号引用转换为调用方法的直接引用

  • 方法返回地址:无论哪种方法,在方法退出后都该回到该方法被调用的位置,因此 方法返回地址 存储调用者的 pc 计数器的值

这里说一下符号引用和直接引用的区别?

符号引用的字面量明确定义在 《Java虚拟机规范》 的 Class 文件格式中

直接引用就是直接指向目标的指针、相对偏移量或简介定位到目标的句柄

栈会溢出吗?

虚拟机栈会溢出的,如果方法调用的过多,导致栈中压入的栈帧太多,就会出现 栈溢出错误

  • 如果线程请求的栈深度大于虚拟机所允许的深度(Xss默认1m),会抛出 StackOverflowError 异常
  • 如果在创建新的线程时,没有足够的内存去创建对应的虚拟机栈,会抛出 OutOfMemoryError 异常

静态方法不能使用 this,而非静态方法中可以使用 this?

如果当前帧(虚拟机栈最上方的帧,即当前执行方法的栈帧)是由构造方法或者实例方法所产生的,那么该对象的 this 引用会被放在局部变量表中 index 为 0 的地方,因此在示例方法和构造方法中可以使用 this 关键字,而在静态方法的局部变量表中没有存储 this 的引用,因此无法使用 this 关键字

可以在 IDEA 中安装 jclasslib 插件,通过该插件来查看文件的字节码:

java 复制代码
public class Test {
    public void testThis() {
        int b = 100;
        System.out.println("testThis");
    }
    public static void testNoThis() {
        int a = 10;
        System.out.println("testNoThis");
    }
}

对于上述生成的字节码文件,我们可以看到 testThis 方法的局部变量表中有 this 变量,而 testNoThis 方法的局部变量表中没有 this 变量,如下图:

本地方法栈

本地方法栈是虚拟机所使用到的 本地方法 ,比如 C++ 方法

一个 Native 方法就是一个 Java 调用非 Java 代码的接口

为什么需要本地方法?

Java是一门高级语言,我们不直接与操作系统资源、系统硬件打交道。如果想要直接与操作系统与硬件打交道,就需要使用到本地方法了

底层就是这么实现的,在多线程部分就会有很多 Java 调用 Native 方法的示例

相关推荐
佛祖让我来巡山1 天前
深入理解JVM内存分配机制:大对象处理、年龄判定与空间担保
jvm·内存分配·大对象处理·空间担保·年龄判定
杨杨杨大侠1 天前
打开 JVM 黑匣子——走进 Java 字节码(一)
java·jvm·agent
J2K2 天前
JDK都25了,你还没用过ZGC?那真得补补课了
java·jvm·后端
Slaughter信仰2 天前
深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)第十章知识点问答(10题)
java·jvm·数据库
2303_Alpha2 天前
SpringBoot
笔记·学习
萘柰奈2 天前
Unity学习----【进阶】TextMeshPro学习(三)--进阶知识点(TMP基础设置,材质球相关,两个辅助工具类)
学习·unity
沐矢羽2 天前
Tomcat PUT方法任意写文件漏洞学习
学习·tomcat
好奇龙猫2 天前
日语学习-日语知识点小记-进阶-JLPT-N1阶段蓝宝书,共120语法(10):91-100语法+考え方13
学习
向阳花开_miemie2 天前
Android音频学习(十八)——混音流程
学习·音视频
工大一只猿2 天前
51单片机学习
嵌入式硬件·学习·51单片机