JVM操作数栈之栈顶缓存(看不懂捶我)

定时移动鼠标点击鼠标,防止电脑息屏的vba脚本 定时移动鼠标,使系统始终处于激活状态,防止系统息屏。 阅读详情

前言

语雀地址:https://www.yuque.com/yangxiaofei-vquku/wmp1zm/mggrlr


基于栈式的架构的虚拟机所使用的零地址指令更加紧凑,单完成一项操作的时候必然需要使用更多的入栈和出栈指令,虚拟机栈也是存在于内存中,这就意味着将需要更多的指令分派次数和内存读/写次数,频繁的执行内存读/写操作必然会影响执行速度,为了解决这一问题HotSpot JVM的设计者们提出了栈顶缓存(Top-of-Stack-Caching)技术,将栈顶元素(或栈顶周边)元素缓存到物理CUP的寄存器中,以此降低对内存的读写次数,提升执行引擎的执行效率。
有关栈顶缓存技术需要关注两个核心问题:

  • 缓存了栈顶附近的多少个元素?如果缓存了n个元素,那么就叫n-TOS caching;
  • 缓存带有多少种“状态”?如果有n种状态那么就叫n-state TOS caching。

1. 先看n-TOS caching

从抽象数据结构来举例操作数栈的实现:可以想像把Java标准库自带的那个java.util.Stack包装一下,假如实现栈顶缓存技术的逻辑如下:压如操作数栈的栈顶元素优先存到CUP的寄存器中。(假设Stack为原始操作数栈,StackWith1TOSCA为支持栈顶缓存的操作数栈)

import java.util.EmptyStackException;  
import java.util.Stack;  
  
public class StackWith1TOSCA<E> {  
  
  private enum TosState {  
    NOT_CACHED,  
    CACHED;  
  }  
  // 内存中的操作数栈(内存)
  private Stack<E> theStack = new Stack<E>();  
  // 栈顶元素(寄存器)
  private E        topOfStackElement; // the cache  
  // 是否有缓存,在1-TOS中即表示栈顶是否有数据
  private TosState state = TosState.NOT_CACHED;  
   
   // 向操作数栈中压如元素
  public void push(E elem) { 
      // 如果栈顶已有元素,
    if (state == TosState.CACHED) { 
        // 将栈顶元素压入内存中真正的操作数栈
      theStack.push(topOfStackElement);  
    }  
      // 将寄存器中栈顶数据替换为新压人的栈顶元素
    topOfStackElement = elem; 
      // 设置state为CACHE代表栈顶有元素
    state = TosState.CACHED;  
  }  
   
    // 操作数栈的栈顶元素出栈
  public E pop() {  
      // 如果状态为NOT_CACHE也就是无栈顶元素,此时操作数栈为空无法出栈
    if (state == TosState.NOT_CACHED) throw new EmptyStackException();  
     // 将CPU寄存器中的栈顶元素取出 
    E result = topOfStackElement;  
      // 内存中的栈桢操作数栈是否为空
    if (theStack.isEmpty()) { 
        // 此时操作数栈为空,栈顶元素弹出为空
      state = TosState.NOT_CACHED;  
      topOfStackElement = null;  
    } else { 
        // 将内存中操作数栈的栈顶元素去除放入寄存器
      topOfStackElement = theStack.pop();  
    }  
      
    return result;  
  }  
}  

那么如果有这样的Java代码:

static void foo(Object o) {  
  Object temp = o;  
}  

对于字节码指令为

用不支持栈顶缓存的操作数栈Stack执行上面字节码指令,执行了2次内存读取两次内存写入,jvm操作为

// 从局部变量表读取写入操作数栈——》一次内存读取,一次内存写入
stack.push(locals[0]);  
// 从操作数栈中读取写入局部变量表——》一次内存读取,一次内存写入
locals[1] = stack.pop();  

用支持栈顶缓存技术的操作数栈StackWith1TOSCA执行上面字节码指令,执行了一次内存读取,一次寄存器写入,一次寄存器读取,一次内存写入,jvm操作为

// 从局部变量表读取,写入寄存器——》一次内存读取,一次寄存器写入
topOfStackElement = locals[0]; 
// 从寄存器读取,写入局部变量表——》一次寄存器读取,一次内存写入
locals[1] = topOfStackElement;  

从上述例子可以看出将栈顶元素缓存寄存器有效的减少了内存的读写次数,而如果选择把栈顶附近的若干个元素缓存在寄存器里的话,在频繁的计算逻辑中将大幅度提升性能。

2.再看n-state TOS caching

前面的StackWith1TOSCA例子里可以看到已经有“state”的概念出现:我们必须要知道当前在缓存里到底有没有值,不然就无从判断压栈/出栈时数据该何去何从了。这个例子用了两种状态,NOT_CACHED和CACHED;对于不关心栈里元素类型的stack caching来说,1-TOS用两种状态就够用了。
实际上“状态”可以记录许多东西,取决于到底要实现怎样的TOSCA。

  • 一个例子:如果我们现在不用1-TOS,而用3-TOS caching的话,那很明显我们的“状态”不但要记录“有没有缓存栈顶元素”,还得记录“到底栈顶附近的三个元素到底放在哪个变量里了”。
  • 另一个例子:如果我们的栈需要跟踪栈里的元素的类型,同时我们使用1-TOS caching的话,那就意味着要记录的“状态”里必须记住栈顶元素是什么类型的。HotSpot VM的解释器就是这样的例子,它虽然只用了1-TOS caching,但它的TosState却有9种有效值。也就是说这个解释器的TOSCA可以描述为1-TOS, 9-state caching。
    大家可以想像一个n > 1的n-TOS如果跟带类型的TOSCA结合起来状态数量的膨胀速度会有多快。
    实际上多数虚拟机就算用了stack caching也只会用1-TOS,因为简单高效;大不了1-TOS外带类型。
    也有复杂一些的例子,例如Sun JDK 1.1.x里的解释器在x86上的实现,它用的是2-TOS, 3-state caching。
8 卡 GPU 服务器与 NVLink/NVSwitch 互联技术 NVLink 是一种点对点的高速互连技术,单条 NVLink 就是一条全双工双路信道,每条 NVLink 链路可以将 2 个 GPU 直连起来,并且每个 GPU 可以提供多条 NVLink 接口连接多个 GPU。另外,PCIe Switch 互联拓扑中的 GPU 之间可能存在 GPU0→Switch0→CPU0→CPU1→Switch1→GPU7 的通信链路,它的通信不可避免的存在一定的延迟,因而更适合用于对信号效率不敏感且追求性价比的使用场景,如:推理、云计算等领域。本文讨论的是单机 GPU 卡间互联。 阅读详情

相关推荐

树莓派3-改装wifi外置天线

声明:本文只是技术性探讨,改装引起的产品损坏等后果,由用户自负! 改装主要有两种方法 方法一:直接替换原来的天线 1、移除原有的小陶瓷天线,就在Made in PRC(或UK)那边的那个 清理一下阻焊剂方便天线接地(图中PRC左侧) 2、焊接天线 天线的屏蔽层焊接到清理完阻焊剂的地方,中间的信号线焊接到PRC右侧焊盘。 3、最终的样子

huayucong的博客 2万+

栈顶缓存技术(Top-of-Stack-Cashing)

栈顶缓存技术和动态链接栈顶缓存技术(Top-of-Stack-Cashing)动态链接(指向运行时常量池的方法引用) 栈顶缓存技术(Top-of-Stack-Cashing) 由于基于栈式架构的虚拟机所使用的零地址指令更加紧凑,但完成一项操作的时候必然需要使用更多的入栈和出栈指令,这同时也就意味着需要更多的指令分派(instruction dispatch)次数和内存读/写次数。 由于操作数是存储在内存中的,因此频繁地执行内存读/写操作必然会影响执行速度。为了解决这个问题,HotSpot JVM的设计者们提

z318913的博客 1252

手把手教你用S7-PLCSIM Advanced V3.0搭建PLC仿真测试环境(含WinPcap避坑指南)

本文详细介绍了如何使用西门子S7-PLCSIM Advanced V3.0搭建PLC仿真测试环境,包括WinPcap 4.1.3驱动的安装避坑指南。从环境准备、软件安装到配置调试,提供了一套完整的解决方案,帮助工程师和教学人员快速构建可靠的PLC仿真环境,解决常见的报错问题。

weixin_30879169的博客 641

【jvm】栈顶缓存技术

1.在基于栈式架构的虚拟机(如Java虚拟机)中,完成一项操作往往需要更多的入栈和出栈指令,这导致了更多的指令分派次数和内存读/写次数。2.当处理器执行指令时,如果需要使用栈顶元素,它可以直接从寄存器中获取,而无需访问内存,从而减少了访问延迟和提高了执行速度。4.栈顶缓存技术是一种有效的计算机体系结构优化技术,它通过减少内存读/写次数和降低访问延迟来提高指令的执行效率。:由于寄存器的数量有限,栈顶缓存技术可能无法缓存所有的栈顶元素,这在一定程度上限制了其性能提升的空间。2.是一种在计算机体系结构中用于。

王佑辉的博客 1309

利用eds editor生成CANOPEN 设备eds文件

通过以上步骤,您可以根据实际设备的功能特性,自动生成一份符合CANopen协议标准的电子数据表(EDS文件),该文件可以被上位机软件或其他CANopen主站设备用于识别、配置和控制您的CANopen从站设备。使用CANopen EDS Editor生成CANOPEN设备的EDS文件是一个系统化的过程,它涉及将设备的具体技术参数和功能映射到CANopen规范定义的对象字典中。

weixin_38604759的博客 6457

告别环境配置烦恼:Docker容器化一站式搭建Zephyr RTOS开发环境

本文详细介绍了如何使用Docker容器化技术一站式搭建Zephyr RTOS开发环境,彻底解决环境配置不一致、依赖冲突等难题。通过预构建镜像、数据卷挂载和实战编译示例,帮助开发者快速获得隔离、一致且可复现的嵌入式开发环境,大幅提升开发效率和团队协作体验。

n8m7b6v5c4的博客 189

什么是栈顶缓存技术

这个缓存可以包含指令的地址和数据,以便快速检索和执行。如果后续指令需要访问之前指令的结果,它们可以从栈顶缓存中获取,而不必等待整个流水线的重新执行。使用栈顶缓存技术,处理器可以在加载数据指令的执行过程中,将加载的数据存储在一个栈顶缓存中,而无需等待整个指令执行完成。需要注意的是,实际的处理器设计和优化比这个简单示例复杂得多,但这个示例可以帮助理解栈顶缓存技术的基本原理,即在流水线中提前加载和存储数据,以减少指令执行的延迟。这种方式可以提高流水线的效率,减少了流水线停滞的可能性,从而提高了指令执行的性能。

Candy___i的博客 955

SAP 实施:Waterfall vs. Agile —— 一场“结构性矛盾“的深刻比较先说结论:在 SAP 世界里,这从来不是“谁更好“的宗教问题,而是“你的项目 DNA 是什么“的战略选择。​

SAP 实施:Waterfall vs. Agile —— 一场"结构性矛盾"的深刻比较 先说结论:在 SAP 世界里,这从来不是"谁更好"的宗教问题,而是"你的项目 DNA 是什么"的战略选择。​ SAP 早已用 SAP Activate​ 给出了官方态度——它不是纯 Agile,也不是回头去搞旧 Waterfall,而是一个带质量门的混合架构。 1. 先回到本质:两者解决的是不同维度的风险 维度 Waterfall(传统 ASAP 路线)​ Agile(SCRUM/Kanban 式迭代)​

金牌架构师 336

栈顶缓存技术

1.将栈顶元素全部缓存在物理CPU中的寄存器中,以降低对内存的读/写次数,提升执行引擎的执行效率。

weixin_45650737的博客 469

基于LSTM算法实现交通流量预测(Pytorch版)

本研究采用PyTorch框架,设计并实现了一种基于LSTM(Long Short-Term Memory)网络的交通流量预测模型。针对时序性显著的交通流量数据,模型首先将多节点、多通道的时空信息整合为一维特征输入至多层LSTM单元,利用其捕捉长期依赖及短期波动的能力进行深度学习。全连接层随后调整时间步长以适应预测周期需求。模型结构灵活,能适应不同节点数、输入输出长度及通道配置,实现在给定历史流量数据基础上对未来交通流量的精准预测,为交通管理与规划提供数据驱动支持。

打酱油的葫芦娃 4634

YOLOv11涨点改进 | 全网独家创新,损失函数改进篇 | TGRS 2025 | 引入AdaFocalLoss损失函数,改进小目标检测,自适应聚焦小目标与样本分布不平衡,提升检测精度与训练稳定性

本文提出了一种改进YOLOv11模型的AdaFocalLoss损失函数,通过动态调节机制有效提升小目标检测性能。AdaFocalLoss融合了目标尺寸感知和IoU引导的自适应调节,解决了传统损失函数在小目标检测中的样本不平衡问题。该方法自动调整训练权重,无需手动调参,显著提升了模型在多尺度目标、复杂背景下的检测精度和训练稳定性。实验表明,AdaFocalLoss能更好地平衡不同尺度目标的梯度分布,改善边界完整性,减少误检漏检。文章详细介绍了算法原理、实现代码和在YOLOv11中的集成方法,为提升目标检测性能

Ai缝合怪、助力小伙伴高效发论文 335

JVM(五) -- 字节码和类的加载(一) -- 方法调用

方法绑定机制 在JVM中,将符号引用转换为调用方法的直接用与方法的绑定机制相关。 静态链接: 当一个字节码文件被装载进JVM内部时,如果被调用的目标方法在编译器可知,且运行期保持不变时。这种情况下将调用方法的符号引用转换为直接引用的过程称之为静态链接。 动态链接: 如果被调用的方法在编译器无法被确定下来,也就是说,只能够在程序运行期将调用方法的符号引用转换为直接引用,由于这种引用转换过程具备动态性,因此也称之为动态链接。 这2种链接方法对应的方法的绑定机制魏:早期绑定和晚期绑定。绑定是一个字段、方法或者类在

weixin_39724194的博客 364

82、yolov11检测模型迁移瑞芯微rk3588和使用昇腾设备300i DUO卡推理 batch=1/3,支持昇腾NMS迁移npu推理

本文介绍了使用昇腾设备进行分割推理的测试流程,包括两种测试方式(cann+onnx和om)。首先验证300iDUO卡的可用性,随后创建Docker镜像和容器以搭建独立环境。通过从指定仓库拉取Ubuntu 20.04镜像,创建容器并映射目录。进入容器后安装必要组件(Python3、GCC等)和系统工具(pciutils、net-tools等),为后续模型转换和迁移做准备。整个流程旨在构建可交付给第三方的标准化测试环境。

sxj731533730 1198

【JVM笔记】操作数栈与栈顶缓存技术

每一个操作数栈都会拥有一个明确的栈深度用于存储数值,其所需的最大深度在编译期就定义好了,保存在方法的Code属性中,为max_stack的值。操作数栈中元素的数据类型必须与字节码指令的序列严格匹配,这由编译器在编译期间进行验证,同时在类加载过程中的类检验阶段的数据流分析阶段要再次验证。操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)/出栈(pop)操作数栈就是JVM执行引擎的一个工作区,当一个方法刚开始执行的时候,一个新的栈帧也会随之被创建出来,.........

lijibai_的博客 502

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

《剑指JVM》——第4章 操作数栈2——栈顶缓存技术——虚拟机栈5——运行时数据区篇8

🔥本篇概览:详细讲解了虚拟机的栈顶缓存技术。🌈⭕🔥

做一个善良的人,做好自己的事,如果愿意,再发一份光。 1127

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

JVM栈(3)-----操作数栈

是什么 我们平常说的Java栈/JVM的执行引擎是基于栈的执行引擎,其实指的栈都是操作数栈 用于在方法执行过程中,根据字节码指令往栈中写入数据或提取数据,即入栈和出栈,主要用于作为变量的临时存储空间,同时保存计算过程中的中间结果。 某些字节码指令将值压入操作数栈,其余的字节码指令将操作数取出栈,使用它们后再把结果压入栈,比如: 执行复制、交换、求和等操作。 操作数栈是JVM执行引擎的一个工作区,当一个方法刚开始执行的时候,会创建一个新的栈帧,这时候栈帧中的操作数栈是空的(空的不代表没有长度)

qq_43332570的博客 832

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

JVM学习:虚拟机栈-操作数栈

一、概念 和局部变量区一样,操作数栈也是被组织成一个以字长为单位的数组。但是和前者不同的是,它不是通过索引来访问,而是通过标准的栈操作—压栈和出栈—来访问的。比如,如果某个指令把一个值压入到操作数栈中,稍后另一个指令就可以弹出这个值来使用。 虚拟机在操作数栈中存储数据的方式和在局部变量区中是一样的:如int、long、float、double、reference和returnType的存储。对于byte、short以及char类型的值在压入到操作数栈之前,也会被转换为int。 不同于程序计数器,Java虚

方猿 442

JVM---虚拟机栈(操作数栈)

虚拟机栈—操作数栈 概念 操作数栈:Operand Stack 每一个独立的栈帧除了包含局部变量表以外,还包含一个后进先出的操作数栈,也可以称之为 表达式栈(Expression Stack); 操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)和 出栈(pop); 某些字节码指令将值压入操作数栈,其余的字节码指令将操作数取出栈,使用它们后再把结果压入栈,比如:执行复制、交换、求和等操作; 操作数栈,主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空

qq_33626996的博客 730

JVM(6):Slot变量槽、操作数栈、代码追踪、栈顶缓存技术

一、Slot变量槽的理解 参数值的存放总是在局部变量数组的index0开始,到数组长度-1的索引结束。 局部变量表,最基本的存储单元是slot(变量槽) 局部变量表中存放编译期可知的各种基本数据类型(8种),引用类型(reference), returnAddress类型的变量。 在局部变量表里,32位以内的类型只占用一个slot(包括returnAddress类型),64位的类型(long和double)占用两个slot。 byte...

游王子og的博客 998

[JVM]操作数栈-虚拟机栈

操作数栈,在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)/出栈(pop)

weixin_51348116的博客 437

JVM栈帧内部结构-操作数栈

基本概念: 操作数栈是基于数组的方式实现的。 在方法执行过程中,根据字节指令,往栈中写入(入栈/push)数据或提取(出栈/pop)数据。 某些字节码指令将值压入操作数栈,其余的字节码指令将操作数取出栈,使用它们后再把结果压入栈。(比如:复制,交换,求和等操作) 操作数栈主要用于保存计算过程的中间结果,同时作为计算过程中变量...

qq_20394285的博客 856

JVM之JVM栈的详细解析

基于栈式架构的虚拟机使用的零地址指令更加紧凑,完成一项操作需要使用很多入栈和出栈指令,所以需要更多的指令分派(instruction dispatch)次数和内存读/写次数,由于操作数是存储在内存中的,因此频繁地执行内存读/写操作必然会影响执行速度,所以需要栈顶缓存技术。的,如果一个局部变量过了其作用域,那么之后申明的新的局部变量就可能会复用过期局部变量的槽位,从而达到节省资源的目的。操作数栈:在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)或出栈(pop)

qq_69748833的博客 1287

【JVM 内存结构丨栈】

JVM内存结构之栈的详解

爱媳妇儿爱编程 4290

欧尼酱讲JVM(10)——操作数栈

首先要明确一个概念:操作数栈在栈帧中。我红色框圈起来的部分。 操作数栈的理解 每一个独立的栈针中除了包含局部变量表以外,还包含一个后进先出的操作数栈,也叫表达式栈。 操作数栈在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈。 某些字节码指令将值压入操作数栈,其余字节码指令将操作数取出栈,使用他们后再把结果压入栈。 比如:执行复制,交换,求和等操作。 操作数栈的特点 操作数栈,主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。 操作数栈就是jvm执行引.

化身孤岛的鲸 575

JVM06_栈帧之操作数栈

操作数栈 操作数栈和局部变量表都是用的数组结构,数组一旦创建,那么长度就固定了。 但是操作数栈不会采用访问索引方式进行数据访问 代码追踪 bipush:byte、short、char、boolean都是以int型来保存,bi代表int型 局部变量表和操作数栈都是基于数组的栈实现的 第一步: bipush是把byte类型转换成int进行保存 PC寄存器中就是保存的指令地址, bipush把15压入操作数栈,int占两个字节,所以下一个指令从2开始 istore_1:表示把int类型的值从操作数栈取出

TimEcho的博客 347

JVM学习- - -虚拟机栈详解

比如:描述一个方法调用了另外的其他方法时,就是通过常量池汇总指向方法的符号引用来表示的,那么。Java7中增加的动态语言类型支持的本质是对Java虚拟机规范的修改,而不是对Java语言规则的修改,这一块相对来讲比较复杂,增加了虚拟机的方法调用,最直接的受益者就是运行在Java平台的动态语言的编译器。如果Java虚拟机栈可以动态拓展,并且在尝试拓展的时候无法申请到足够的内存,或者在创建新的线程时没有足够的内存区创建对应的虚拟机栈,那Java虚拟机栈将会抛出一个OutOfMemoryError异常。

退役复学在校大学生,目光所至,皆为华夏 3万+
上一篇: 内存分页机制完全攻略
下一篇: java虚拟机栈(亦篇足以,吴懈可击)
躺平程序猿
博客等级 码龄8年 4870粉丝 71原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

躺平程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值