当前位置: 首页 > news >正文

JVM字节码加载与存储中的细节

问题引出:

为什么Java定义int型变量为32767时使用的是bipush 32767,而定义int型变量为32768时使用的是 ldc #4 <32768> ?

在 Java 中,如果这样定义int型变量:

public class Test {public static void main(String[] args) {int i = 0;int j = 5;int k = 6;int m = 32768;int n = 32767;}
}

变量对应的字节码文件内容是这样的:

 0 iconst_01 istore_12 iconst_53 istore_24 bipush 66 istore_37 ldc #2 <32768>9 istore 4
11 sipush 32767
14 istore 5
16 return

其中可以看到,当变量值为0~5时,使用的是iconst_x(x为值)的命令来操作的,当变量值为6时,采用bipush 6的命令来操作,但当值为32768时,却采用了ldc命令结合常量池的形式,但是在值为32767时,仍然使用的是sipush 32767的形式来操作的,于是好奇为什么相邻的int值采用了不同的命令来操作。

猜想:与Integer在-128到127之间的值是直接从缓存中取的思路可能一致,为了保证效率而做的优化。

查找资料后,得到的答案是:

核心原因:

是由于 JVM 指令集的设计限制和效率考虑导致的:

✅ bipush 的作用与限制:

  • bipush(byte integer push):将一个 单字节有符号整数(即范围为 -128 ~ 127)推入操作数栈。
  • 它后面跟的是一个 8位带符号整数(即只能表示 -128 到 127)。

但是!

Java 编译器做了一个“扩展”,它允许你在某些情况下使用 bipush 来处理更大一点的整数,比如 short 类型范围内的(-32768 到 32767),但本质上仍然是把值当作 byte 扩展成 int 处理。

不过,一旦超过 127(或小于 -128),就不能再使用 bipush,因为它的参数是 1 字节的有符号整数。

所以:

  • 32767 超过了 bipush 支持的范围(-128 ~ 127),但它仍然能被优化地编码进字节码;
  • 32768 就不能使用 bipush,必须使用更通用的方式加载,如 ldc

✅ ldc 是什么?

  • ldc 是 "load constant" 的缩写。
  • 它从 运行时常量池(Runtime Constant Pool)中加载一个常量值到操作数栈。
  • 可以用于加载:
    • int
    • float
    • String
    • 类引用等复杂结构

当数值超过 bipushsipushiconst_x 等直接加载指令支持的范围时,Java 编译器就会将其放入常量池,并使用 ldc 加载。

具体分析:

数值使用指令原因说明
-1iconst_m1特殊指令
0 ~ 5iconst_0iconst_1 ... iconst_5有专门的短指令
6 ~ 127bipush x单字节可表示
128 ~ 32767sipush x使用双字节有符号整数
≥ 32768ldc #x放入常量池,使用 ldc 加载

所以:

  • 32767 可以用 sipush 32767(因为是 short 最大值)
  • 32768 已经超过了 short 的最大值(32767),只能用 ldc 加载

✅ 总结:

指令支持范围用途说明
iconst_x-1 ~ 5特定小整数专用指令
bipush-128 ~ 127单字节整数
sipush-32768 ~ 32767双字节整数
ldc任意整数(放入常量池即可)加载超出上述范围的整数

❗ 结论:

  • 32767 属于 sipush 支持的最大值范围内,所以用 sipush 32767
  • 32768 超出 sipush 范围,必须使用 ldc 从常量池加载

这就是会看到不同指令的原因 —— 是 JVM 指令设计与编译器优化共同作用的结果

 

http://www.xdnf.cn/news/1090531.html

相关文章:

  • 川翔云电脑:突破硬件极限,重构设计生产力范式
  • 【vim中替换】
  • 【自动驾驶】经典LSS算法解析——深度估计
  • BEV感知算法:自动驾驶的“上帝视角“革命
  • django 一个表中包括id和parentid,如何通过parentid找到全部父爷id
  • 免费扫描软件NAPS2:跨平台支持 旋转裁剪 + 多页合并,纸质文档变 PDF / 图片
  • 详解Kafka重平衡机制详解
  • Python(30)基于itertools生成器的量子计算模拟技术深度解析
  • 18-C#改变形参内容
  • 《设计模式之禅》笔记摘录 - 5.代理模式
  • AI应用实践:制作一个支持超长计算公式的计算器,计算内容只包含加减乘除算法,保存在一个HTML文件中
  • 设计模式(行为型)-责任链模式
  • Flink Forward Asia 2025 主旨演讲精彩回顾
  • 两张图片对比clip功能
  • React 19 概览:新特性与生态系统变革
  • 1.1 ARMv8/ARMv9安全扩展
  • 网络安全之RCE分析与利用详情
  • 前端使用Web Cryptography API进行内容加密,几乎无法破解
  • 循环神经网络详解
  • 数据结构之位图和布隆过滤器
  • Web 前端框架选型:React、Vue 和 Angular 的对比与实践
  • [特殊字符] 突破小样本瓶颈:DataDream——用Stable Diffusion生成高质量分类数据集
  • “AI 曼哈顿计划”:科技竞赛还是人类挑战?
  • VUE混合开发,选哪个PHP框架最顺手?
  • 【Qt】Qt QML json处理
  • Qt的信号与槽(三)
  • uniapp小程序无感刷新token
  • 【数字后端】- Standard Cell Status
  • 【机器人】Aether 多任务世界模型 | 4D动态重建 | 视频预测 | 视觉规划
  • vue2中使用xgplayer播放流视频