用Java手写jvm之模拟运行时数据区的虚拟机栈,局部变量表,操作数栈等

news2024/11/15 18:19:06

写在前面

下图是jvm的运行时数据区内存图:
在这里插入图片描述
,本文要模拟的是虚拟机栈的相关内存结构的交互过程。

1:正文

因为我们这里模拟的是线程执行方法调用的过程,所以这里先来定义一个线程对象:

public class Thread {

    // 程序计数器 program counter
    private int pc;

    // 线程虚拟机栈,每个线程都会被分配这样的一块内存区域
    private JvmStack stack;

    public Thread(){
        this.stack = new JvmStack(1024);
    }

    public void setStack(JvmStack stack) {
        this.stack = stack;
    }

    public int pc(){
        return this.pc;
    }

    public void setPC(int pc){
        this.pc = pc;
    }

    public void pushFrame(Frame frame){
        this.stack.push(frame);
    }

    public Frame popFrame(){
        return this.stack.pop();
    }

    public Frame currentFrame(){
        return this.stack.top();
    }

}

这里的JvmStack就是给每个线程分配的线程栈,如下:

public class JvmStack {

    private int maxSize;
    private int size;
    // 线程虚拟机栈的方法的当前栈帧
    private Frame _top;

    // ...
}

Frame是线程栈的中栈帧,对应线程中的一个方法的调用,如下:

public class Frame {

    //stack is implemented as linked list
    Frame lower;

    //局部变量表
    private LocalVars localVars;

    //操作数栈
    private OperandStack operandStack;

    public Frame(int maxLocals, int maxStack) {
        this.localVars = new LocalVars(maxLocals);
        this.operandStack = new OperandStack(maxStack);
    }

    public LocalVars localVars(){
        return localVars;
    }

    public OperandStack operandStack(){
        return operandStack;
    }

}

在栈帧中有一个指向下一个栈帧的引用,这样才能实现一个方法调用另一个方法。LocaVars就是栈帧的局部变量表,OperandStack是栈帧的操作数栈,如下:

public class LocalVars {

    private Slot[] slots;

    public LocalVars(int maxLocals) {
        if (maxLocals > 0) {
            slots = new Slot[maxLocals];
            for (int i = 0; i < maxLocals; i++) {
                slots[i] = new Slot();
            }
        }
    }

    // ...
}
public class OperandStack {

    private int size = 0;
    private Slot[] slots;

    public OperandStack(int maxStack) {
        if (maxStack > 0) {
            slots = new Slot[maxStack];
            for (int i = 0; i < maxStack; i++) {
                slots[i] = new Slot();
            }
        }
    }
	// ...
}

Slot是一个数据单元,表示在局部变量表以及操作数栈的一个数据项,如下:

/**
 * 本地变量表的数据槽,本地变量表就是一个数据槽组成的数组结构
 */
public class Slot {
    // 槽数据
    public int num;
    //
    public Object ref;

    @Override
    public String toString() {
        return "Slot{" +
                "num=" + num +
                ", ref=" + ref +
                '}';
    }
}

接着我们编写代码来模拟如下代码的执行过程:

public class BBB {
    public static void main(String[] args) {
        int a = 9;
        int b = 8;
        int c = a + b;
        System.out.println(c);
    }
}

测试代码:

package com.dahuyou;

import com.dahuyou.tryy.too.simulate.runtime.area.*;
import com.dahuyou.tryy.too.simulate.runtime.area.Thread;

import java.util.Arrays;

public class Mm {
    public static void main(String[] args) {
        // 模拟创建线程
        Thread thread = new Thread();
        // 创建线程的虚拟机栈
        JvmStack jvmStack = new JvmStack(1000);
        thread.setStack(jvmStack);

        // 模拟如下的方法作为当前栈帧
        /*
        public void fn() {
            int a = 9;
            int b = 8;
            int c = a + b;
        }
        */
        // 指定本地变量表大小和操作数栈大小都是10,这里仅仅是测试了,不用在意这个值,jvm实际运行时会根据具体的方法来动态的设置这个值
        Frame frame = new Frame(10, 10);
        // 设置本地变量表
        LocalVars localVars = frame.localVars();
        localVars.setInt(0, 9);
        localVars.setInt(1 , 8);

        // 模拟代码执行过程
        /*
        ILOAD 1
        ILOAD 2
        IADD
        ISTORE 3
         */
        System.out.println("执行ILOAD 1指令将局部变量表2位置数据压到栈顶");
        OperandStack operandStack = frame.operandStack();
        operandStack.pushInt(localVars.getInt(0));
        System.out.println("执行ILOAD 2指令将局部变量表2位置数据压到栈顶");
        operandStack.pushInt(localVars.getInt(1));
        System.out.println("执行IADD指令,从操作数栈弹出2个数据,并执行加法");
        int param1 = operandStack.popInt();
        int param2 = operandStack.popInt();
        int result = param1 + param2;
        System.out.println("相加后的结果为:" + result);
        System.out.println("执行ISTORE 3指令将相加后的结果保存到局部变量表槽位3的位置");
        localVars.setInt(2, result);


        System.out.println("-----当前局部变量表的数据-----");
        System.out.println(Arrays.asList(localVars.getSlots()));
    }
}

运行:

执行ILOAD 1指令将局部变量表2位置数据压到栈顶
执行ILOAD 2指令将局部变量表2位置数据压到栈顶
执行IADD指令,从操作数栈弹出2个数据,并执行加法
相加后的结果为:17
执行ISTORE 3指令将相加后的结果保存到局部变量表槽位3的位置
-----当前局部变量表的数据-----
[Slot{num=9, ref=null}, Slot{num=8, ref=null}, Slot{num=17, ref=null}, Slot{num=0, ref=null}, Slot{num=0, ref=null}, Slot{num=0, ref=null}, Slot{num=0, ref=null}, Slot{num=0, ref=null}, Slot{num=0, ref=null}, Slot{num=0, ref=null}]

Process finished with exit code 0

可以看到局部变量表第三个槽位存储的就是计算的结果17了。

写在后面

参考文章列表

jvm内存结构 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1972426.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

卸载Windows软件的正确姿势,你做对了吗?

前言 今天有小伙伴突然问我&#xff1a;她把软件都卸载了&#xff0c;但是怎么软件都还在运行&#xff1f; 这个问题估计很多小伙伴都是遇到过的&#xff0c;对于电脑小白来说&#xff0c;卸载Windows软件真的真的真的是一件很难的事情。所以&#xff0c;今天咱们就来讲讲&am…

springboot贫困生认定和资助管理系统-计算机毕业设计源码71367

摘要 本文介绍了一个基于Java的贫困生认定和资助管理系统的设计与实现。该系统旨在通过自动化、智能化的管理方式&#xff0c;提高贫困生认定和资助工作的效率与准确性。系统采用Java作为主要开发语言&#xff0c;结合了数据库技术和Web开发技术&#xff0c;实现了贫困生信息的…

运维之路----计算机基础

目录 ​编辑 一&#xff0c;计算机的组成 1&#xff0c;硬件 2&#xff0c;软件 二&#xff0c;计算机中的一些概念 冯诺依曼体系 二进制 摩尔定律 计算机的分类 1&#xff0c;按照规模分 2&#xff0c;按照功能分 拓扑 存储器的层次结构 并行与并发 缓存 操作系…

实例分割-Yolact/Yolact++训练自己数据集

前言 本文主要用于记录实例分割模型yolact和yolact的环境配置&#xff0c;以及成功训练自己数据集的整个过程~ 注意&#xff1a;这里要重点提醒一下&#xff0c;DCNv2对RTX系列不友好&#xff0c;我第一次使用4090服务器&#xff0c;编译持续有问题&#xff0c;被迫放弃&#…

C++|设计模式(八)|⭐️工厂模式?错!是工厂模式群!

本文内容全部来源于B站&#xff0c;仅做个人学习使用&#xff1a; 【工厂模式&#xff1f;错&#xff01;是工厂模式群&#xff01;】 在此之前&#xff0c;笔者曾经发过两篇关于工厂模式的博客&#xff1a; C&#xff5c;设计模式&#xff08;二&#xff09;&#xff5c;简单…

软件测试---Jmeter

一、简介 二、安装与启动 &#xff08;1&#xff09;安装 安装包&#xff1a;通过百度网盘分享的文件&#xff1a;jmeter环境.rar 链接&#xff1a;https://pan.baidu.com/s/1OB0IP3W7hqUjAGj_5F56sQ

vue3 自定义指令 自动获取节点的width 和 height

想写一个依赖库, 但是需要监听组件的width和height这些数据, 就找到了ResizeObserver这个方法,不想每次使用的时候都要创建和销毁 ResizeObserver, 索性就直接封装成为一个指令用来获取想要的信息, ResizeObserver对象上能够获取的信息还是非常多的, 除了width, height 还有 to…

一篇文章讲明白Ldraw(乐高模型)的格式文件说明

最好将文章内容保存下来 https://ldraw.org/article/218.html 乐高模型是非常有意思的模型&#xff0c;弄明白了它的模型构造&#xff0c;也就懂了三维模型的构造&#xff0c;原理都是相通的。

如何在行空板上运行 YOLOv10n?

YOLOv10介绍 YOLO&#xff08;You Only Look Once&#xff09;系列是当前最主流的端侧目标检测算法&#xff0c;由Joseph Redmon等人首次提出&#xff0c;并随着时间发展&#xff0c;已经推出了多个版本&#xff0c;每个版本“似乎”都在性能和速度上有所提升。 本文为大家介绍…

【前端编程小白】的HTML从零入门到实战

之前有高中毕业生读了博客&#xff0c;想让我帮他找一些前端入门的内容&#xff0c;他们报的计算机专业&#xff0c;想利用开学前夕学习一下&#xff0c;我给他推荐了一些菜鸟教程呀什么的。后来想&#xff0c;看来还是很多人需要一些更加入门的可成的&#xff0c;而且很多教程…

24年电赛——自动行驶小车(H题)基于 CCS Theia -陀螺仪 JY60 代码移植到 MSPM0G3507(附代码)

前言 只要搞懂 M0 的代码结构和 CCS 的图形化配置方法&#xff0c;代码移植就会变的很简单。因为本次电赛的需要&#xff0c;正好陀螺仪部分代码的移植是我完成的。&#xff08;末尾附全部代码&#xff09; 一、JY60 陀螺仪 JY60特点 1.模块集成高精度的陀螺仪、加速度计&…

APACHE安装与应用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

24澳中博览会|2025非洲水协年会暨展览|2025山西水展

2024澳中博览会 2025非洲水协年会暨展览 2025年山西国际水展暨水利工程设计与施工、水处理技术设备、泵管阀、智慧水务及环保展 承办单位&#xff1a;山西泽嘉国际展览有限公司 上海泽嘉展览服务有限公司 战略合作伙伴 &#xff1a; 美国迈阿密水展 欧 洲 海 水 脱 盐 淡 化…

SD原班人马发布FLUX.1:打开AI绘画新世界

​ Black Forest Labs 旗下产品 AI 绘画工具如雨后春笋般涌现&#xff0c;让我们对创作的理解不断刷新。就在大家以为已经见识了 AI 绘画的天花板时&#xff0c;FLUX.1 出现了&#xff01;这款由 Black Forest Labs 推出的 AI 绘画工具&#xff0c;不仅在性能上远超竞品&#x…

不好用你打我!2024你必须要会的AI神器

这篇文章&#xff0c;除了干货就是干货~ 今天给大家介绍一款2024年你必须要掌握的AI神器。 我可以肯定的说他是目前市面上第一款在这个领域出现的AI工具。 现在的AI工具&#xff0c;可以用来生成文字、图片、视频甚至音乐&#xff0c; 但是你听说过直接用AI生成APP的吗&…

【Spring】Spring框架的概念,以及Spring框架的简单使用。

目录 1. 概念 2. Spring的体系结构介绍&#xff08;了解&#xff09; 3. Spring框架的使用 3.1 环境准备 3.2 代码编写 1. 概念 总的来说就是一句话&#xff0c;Spring框架是一个轻量级的控制反转&#xff08;IoC&#xff09;和面向切面&#xff08;AOP&#xff09;编程的容…

Spring Boot+MyBatis+MySQL如何实现读写分离

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 背景 读写分离是数据库架构中的一种优化策略&#xff0c;它将读操作&#xff08;查询&#xff09;和写操作&#xff08;更新、插入、删除&#xff09;分开处理&#xff0c;通常通过将读请求和写请求分别发送…

2024年全国青少年信息素养大赛总决赛日赛程表

2024全国青少年信息素养大赛赛程表分赛场&#xff08;浙江传媒学院桐乡校区、桐乡技师学院&#xff09;日期地点时间赛项16日传媒学院8:00-9:00检录 9:00-10:30开赛图形化编程挑战赛&#xff08;小学1-3年级&#xff09;A组12:00-13:00检录 13:00-14:30开赛图形化编程挑战赛&am…

最新版Baby Audio Bundle,win和mac,持续更新,长期有效

一。Baby Audio Bundle.2024.07.WiN&MAC Baby Audio让您的混音听起来比以往任何时候都更大&#xff0c;更好&#xff0c;更有活力。这个捆绑包有七个独特的插件&#xff0c;涵盖了从延迟和混响效果&#xff08;Spaced Out&#xff09;到低保真声音&#xff08;Super VHS&am…

MySQL(8.0)数据库安装和初始化以及管理

1.MySQL下载安装和初始化 1.下载安装包 下载地址&#xff1a;https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar 2.解压…