关于栈的存储结构与运行原理分析-创新互联

关于栈的存储结构与运行原理分析 关于虚拟机栈出现的背景

由于对于不同的处理器(ARM/X86)内部的寄存器的设计架构是不同的,Java 语言为了实现 “Write once Run everywhere” 的口号,内部的指令都是通过栈来实现的。

成都创新互联公司成立10年来,这条路我们正越走越好,积累了技术与客户资源,形成了良好的口碑。为客户提供网站设计、成都网站建设、网站策划、网页设计、空间域名、网络营销、VI设计、网站改版、漏洞修补等服务。网站是否美观、功能强大、用户体验好、性价比高、打开快等等,这些对于网站建设都非常重要,成都创新互联公司通过对建站技术性的掌握、对创意设计的研究为客户提供一站式互联网解决方案,携手广大客户,共同发展进步。

栈是程序的运行时的单位,而对于堆更像是数据的存储单位。

栈:程序运行时调用的各种功能性的方法处理解决数据问题

堆:用于存放数据,比如创建的对象,静态的变量

关于程序的方法的栈帧解读

创建一个类如下代码所示:

public class MyStackTest {public static void main(String[] args) {int number = 10;
        double num = 20.0d;
        Date date = new Date();
        System.out.println("Hello World!!!");
    }
}

通过 jcalsslib 工具查看编译过的 class 文件

image-20230109211052960

对于当前的 MyStackTest.class 类文件中在方法中可以看到有两个文件与 main ,init 是构造器,main对应的是 main 方法

关于方法
  • 无参构造方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AYtDQ0ZT-1673321219762)(关于栈的存储结构与运行原理分析.assets/image-20230110112111380.png)]

  • 有参构造方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qAywoO6K-1673321219762)(关于栈的存储结构与运行原理分析.assets/image-20230110112145675.png)]

  • 有参有返回值的静态方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5iZ5ULVV-1673321219763)(关于栈的存储结构与运行原理分析.assets/image-20230110112440601.png)]

  • 有参无返回值的非静态方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-62z0uSat-1673321219764)(关于栈的存储结构与运行原理分析.assets/image-20230110112541026.png)]

main方法解析

image-20230109211511975

对于 main 方法

名称: 地址索引为 #18 方法名

该名来自于

描述符: 地址索引为 #19 形参为 java.lang.String 包路径下的 L (引用数据类型) 为 [(数组) String 返回值类型 V(void)

访问标志:[public static]

image-20230109212938163

操作数栈大深度:2 (与数据的类型有关是固定的 32bit的类型占用一个栈单位 64bit的类型占用两个栈单位)

局部变量大槽数: 5 (局部变量的个数,一个局部变量占用栈帧的一个槽位)

字节码长度:表示字节码所占用的行数

比如该类中的 main 占用 25 行

0 bipush 10
 2 istore_1
 3 ldc2_w #2<20.0>6 dstore_2
 7 new #410 dup
11 invokespecial #5: ()V>14 astore 4
16 getstatic #619 ldc #721 invokevirtual #824 return

第一部分:

​ [0]LineNumberTable

​ Nr. 表示局部变量的所占槽位置

​ 起始PC 字节码所在行号

​ 行号 在源代码中的行号

image-20230109213025484

第二部分:

​ [1] LocalVariableTable

​ Nr. 表示局部变量的所占槽位

​ 起始PC 字节码所在行号 该局部变量的起始作用位置

​ 长度 25 + 0 = 25 (表示整个该方法的整个字节码的长度) 该字节码的结束作用位置

​ 序号 字节码

​ 名字 局部变量

​ 起始PC + 长度 = 局部变量的作用域范围

image-20230110093715289

槽 一个局部变量占用一个槽位
局部变量表实际上在我们的内存结构上是以 数组的形式进行存储的

局部变量的重复利用
public class MyStackTest {public void test() {int i = 0;
        {int b = 0;
            b = i + 1;
        }
        int c = 0;
        c = i + 1;
    }
}

image-20230110100732307

image-20230110100753602

可以看到代码块中的变量 b 的起始PC为 4 结束长度为 4 整个作用域的大小为 8

可以看到在本地变量表中,有四个局部变量,分别是内部代码块中的 b , 非静态方法局部变量 this 以及其他两个定义变量 i 与 c ,但是 test 方法的局部变量的大槽数却是 3 也就是说给 test 方法所在栈帧中分配了 3 个局部变量的空间,这与本地局部变量表展现出来的结果出现了歧义。

那么为什么会出现这样的问题呢?

这是因为 内部代码块中代码作用域只是作用与代码块的内部,只是在编译期间起到作用,所以为了节省栈内空间就未给栈帧中局部变量分配槽位。
image-20230110113011757

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻标题:关于栈的存储结构与运行原理分析-创新互联
文章位置:http://pwwzsj.com/article/gcogj.html