java 虚拟机浅析(四)JVM运行时栈空间的内部状态解析

前言

本文主要介绍JVM运行时,内存中数据的布局情况,主要是介绍JVM栈的状态更迭。

本文会通过查看一个类文件编译后的字节码文件,来分析当一个方法执行的时候,JVM中的栈空间所发生的变化。

JVM内存的整体布局

当JVM运行时,内存主要由程序计数器(Program Counter),(stack),直接内存区(Direct Memory),方法区(Method Area),(Heap)。

栈又可以分成两部分,分别是JVM StackNative Method Stack

每个线程都有自己独立的程序计数器和栈,同时共享方法区和堆,具体情况如下图所示:

在这里插入图片描述
上图中需要我们注意的重点是:

每个线程有自己独立的栈空间。栈空间中的数据都是当前线程独有的。

JVM中的栈空间

JVM中每个线程的栈分为两部分,分别是JVM Stack和Native Method Stack。

由于Native Method Stack涉及到C和C++的知识,超出本文的范围,所以这里不做讨论,只讨论JVM Stack的情况。

当讨论JVM 栈的时候,就不得不说另一个概念——栈帧

栈帧

栈里的每一个元素就是一个栈帧(Stack Frame),一个方法的调用就会产生一个栈帧。

先介绍一下栈帧的内部结构。

栈帧的内部结构

栈帧内部其实分成了以下四个部分,

Local Variables:记录数据和中间结果。

Operand Stack:操作数栈,每个栈帧内部还存在一个栈,这个栈中存放的是执行操作需要的数据。

Dynamic Linking:栈中指向常量池的引用,如果常量池中的对象没有被解析就动态解析,如果被解析了就直接拿过来用。有点类似于ClassLoader中Linking步骤的resolusion执行的操作

Return Address:指生成当前栈帧的方法,执行完毕后应该去哪个地址接着执行。

字节码与栈动态

首先我们有下面这段java源代码:

public class ByteCodeDemo {
    public static void main(String[] args) {
        int i = 1;

        i = i++;

        System.out.println(i);
    }
}

上面的源代码编译后的字节码文件如下:

在这里插入图片描述

这段代码只有一个方法,就是main方法,所以只有一个栈帧。

先来看看栈帧中的Local Variables Table中的内容:

在这里插入图片描述
可以看到,在本地变量表中有两个数据,索引为0的变量是方法的参数args,索引为1的是方法内声明的变量i

接下来我们通过字节码文件来演示Operand Stack中的变化。

  1. 当方法刚开始执行的时候,执行数栈是一个空栈。
    在这里插入图片描述

  2. 执行字节码中的第一行命令iconst_0后,常量值0添加到栈中。

在这里插入图片描述

  1. 执行第二条命令时istore_1,是指将栈顶元素弹出,把该元素的值赋予本地变量表中索引为1的变量,在示例代码中,就是把0赋值给i。

    在这里插入图片描述

  2. 执行第三条命令,也就是iload_1,是指将局部变量表中索引为1的变量值加入到操作数栈中,也就是将0压到栈中。

    在这里插入图片描述

  3. 执行iinc 1 by 1,是指将局部变量表中索引为1的变量,自增1次。也就是在局部变量表中在索引1位置上的0,变为1,注意,此时操作数栈中的元素值仍是0。

    在这里插入图片描述

  4. 再次执行istore_1,将栈顶元素弹出,把该元素的值赋予本地变量表中索引为1的变量。

    在这里插入图片描述

  5. 接下来就是执行打印语句了,这里就不在进行介绍。

所以最后的输出的i的值是0,而不是1。

补充:如果一个方法有返回值的,会将返回值放在该方法的调用方法栈帧中的操作数栈的栈顶。调用方法再调用pop()方法就能拿到该方法的返回值。

总结

本文首先从整体来介绍了JVM运行时,内存中各组件的分配布局,包括线程独有的栈空间和程序计数器,以及线程共享的方法区与堆空间。

随后通过一段java代码编译后生成的字节码,介绍了JVM运行时,栈空间中的各部件的状态演变,主要是本地变量表操作数栈之间的交互与演变。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值