JVM规范第 6 章:Java 虚拟机指令集
基于 Oracle 官方《The Java Virtual Machine Specification》第 6 章Java SE 26编写。这是什么为什么值得懂读懂本章你能看javap -c输出时知道0xb6为什么写成invokevirtual、它在栈上怎么取参数理解「为什么long/double在栈上占一项、但某些指令要成对处理」真正搞懂i背后是iincx a b背后是iload iload iadd istore在排查诡异的StackOverflowError、VerifyError时直达字节码层。1. 指令的物理本质opcode 只占 1 字节8 位因此最多 256 种操作码。这就是 JVM 指令集「精简」的根本原因。一条指令 1 字节 opcode 可选操作数操作数长度因指令而异所以指令长度可变。操作数大多从操作数栈隐式取得第 2 章讲过的栈机器模型而非寄存器编号——这让编译产物紧凑。少数操作数在编译期就嵌入指令如iload 2里的2是局部变量槽号ldc #7里的#7是常量池索引。1.1 指令描述记法每条指令条目按统一格式书写操作码(mnemonic) 操作码值十进制 (0x十六进制) Forms家族成员与各自 opcode如 iconst_i 操作数栈图..., in1, in2 → ..., out 描述 异常链接/运行期此外仅允许 VirtualMachineError 子类操作数栈记法栈从左向右增长栈顶在最右。..., value1, value2 → ..., result表示执行前value2在栈顶、value1次之执行后两者弹出、压入result。long/double在栈上算一项但占两个字宽。1.2 保留操作码与虚拟机错误保留操作码不出现在合法 class 文件里0xcabreakpoint、0xfeimpdep1、0xffimpdep2——仅供实现内部调试/扩展用。wide指令0xc4为操作数扩成 2 字节用于访问索引 255 的局部变量或常量池项。VirtualMachineError子类指令仅允许抛这些InternalError、OutOfMemoryError、StackOverflowError、UnknownError。2. 常量与压栈Constants把常量/引用压入操作数栈。小常量有「快车道」专用操作码第 3 章useManyNumeric示例里见过。指令opcode格式操作数栈说明aconst_null0x01—→ null压入 null 引用iconst_m10x02—→ -1int -1iconst_i0x03–0x08—→ i(i 0…5)int 0~5每值一个 opcodelconst_l0x09–0x0a—→ l(l 0,1)long 0/1fconst_f0x0b–0x0d—→ f(0/1/2)float 0/1/2dconst_d0x0e–0x0f—→ d(0/1)double 0/1bipush0x10byte→ value压入 1 字节有符号立即数sipush0x11short→ value压入 2 字节立即数ldc0x12index(1B)→ value从常量池#index加载int/float/String/类ldc_w0x13index(2B)→ value同ldc索引 2 字节ldc2_w0x14index(2B)→ value加载long/double第 3、4 章讲过的双槽常量记忆法i/l/f/d/a分别是 int/long/float/double/reference 的前缀const是常量push是立即数ldc是 load constant从常量池。3. 局部变量加载与存储Loads / Stores在局部变量表第 2 章 §2.6槽位 0 是this与操作数栈之间搬运值。指令opcode格式操作数栈说明iload0x15index→ value加载 int 局部变量槽 indexiload_n0x1a–0x1d—→ value(n0…3)加载槽 0~3 的 int省 1 字节操作数lload0x16index→ value加载 long占 2 槽fload0x17index→ value加载 floatdload0x18index→ value加载 double占 2 槽aload0x19index→ value加载引用对象/数组istore0x36indexvalue →存 int 到局部变量istore_n0x3b–0x3e—value →(n0…3)存槽 0~3 的 intlstore/fstore/dstore/astore0x37/0x38/0x39/0x3aindexvalue →对应类型存储数组元素加载/存储下标在栈上指令opcode操作数栈说明iaload0x2earrayref, index → valueint 数组取元素iaload/faload/baload/caload/saload0x2e–0x35同构各基本类型数组取元素aaload0x32arrayref, index → value引用数组取元素§6.5 示例弹出引用数组与 int 索引取组件引用压栈iastore/fastore/bastore/castore/sastore/aastore0x4f–0x53arrayref, index, value →各类型数组存元素家族规律areference、iint、llong、ffloat、ddouble、bbyte/boolean、cchar、sshortload取、store存、aloadaload。4. 算术运算Arithmetic全部在操作数栈上完成。整数用补码、浮点用 IEEE 754第 2 章。指令opcode操作数栈说明iadd0x60value1, value2 → resultint 加ladd0x61value1, value2 → resultlong 加fadd0x62→ resultfloat 加dadd0x63→ resultdouble 加isub0x64value1, value2 → resultint 减value1 - value2imul0x68→ resultint 乘idiv0x6cvalue1, value2 → resultint 除抛ArithmeticException当除 0irem0x70→ resultint 取余ineg0x74value → resultint 取负ishl/ishr/iushr0x78/0x7a/0x7cvalue1, value2 → result左移/算术右移/逻辑右移iand/ior/ixor0x7e/0x80/0x82→ result按位与/或/异或对应l/f/d家族0x61~0x83同构long/float/double 算术idiv/ldiv抛ArithmeticException属于运行期检查异常第 2 章讲过。iinc见下是唯一个「直接修改局部变量、不进出栈」的算术指令。iinc0x84indexconst→ 把局部变量index的 int原地加 constvalue → valueconst。这是i的高效实现不碰操作数栈。5. 类型转换Type Conversion指令opcode操作数栈说明i2l0x85value → resultint → longi2f0x86→ resultint → floati2d0x87→ resultint → doublel2i0x88→ resultlong → int截断l2f/l2d0x89/0x8a→ resultlong → float/doublef2i/f2l/f2d0x8b–0x8d→ resultfloat 转换d2i/d2l/d2f0x8e–0x90→ resultdouble 转换i2b0x91value → resultint → byte截断第 2 章讲过i2c0x92→ resultint → chari2s0x93→ resultint → shorti2b/i2c/i2s也用于「窄化」——配合第 3 章sspinshort 循环用i2s截断理解。6. 对象创建与访问Object Creation / Access指令opcode格式操作数栈说明new0xbbindex(2B)→ objectref创建对象未初始化第 3 章newdupinvokespecial initnewarray0xbcatypecount → arrayref创建基本类型数组anewarray0xbdindex(2B)count → arrayref创建引用类型数组multianewarray0xc5index,dimensions→ arrayref创建多维数组第 3 章3D 只定前两维getfield0xb4index(2B)objectref → value取实例字段解析 §5.4.3.2putfield0xb5index(2B)objectref, value →写实例字段getstatic0xb2index(2B)→ value取静态字段putstatic0xb3index(2B)value →写静态字段arraylength0xbearrayref → length取数组长度instanceof0xc1index(2B)objectref → result类型判断1/0checkcast0xc0index(2B)objectref → objectref类型强转失败ClassCastExceptionnew后对象处于「未初始化」状态必须紧跟invokespecial init第 3 章详解。字段/静态指令的index都指向常量池里的Fieldref。7. 操作数栈操作Operand Stack Manipulation不按类型纯栈结构操作。long/double占一项两条槽。指令opcode操作数栈说明pop0x57value →弹出栈顶 1 字宽pop20x58value2, value1 →弹出 2 字宽long/doubledup0x59value → value, value复制栈顶dup_x10x5avalue2, value1 → value1, value2, value1复制并插入栈顶下 1 位dup_x20x5b复杂复制插到栈顶下 2 位dup2/dup2_x1/dup2_x20x5c–0x5e—复制 2 字宽long/double的变体swap0x5fvalue2, value1 → value1, value2交换栈顶两字宽new Object()用的就是dup——new压入未初始化对象再dup一份供init消费、留一份作结果。8. 控制转移Control Transfer条件跳转的「比较」直接在栈上做结果为分支偏移量。指令opcode操作数栈说明ifeq0x99value →value 0 则跳转ifne0x9avalue →value ! 0 则跳转iflt/ifge/ifgt/ifle0x9b–0x9evalue →与 0 比较 / ≥ / / ≤if_icmpeq0x9fv1, v2 →两 int 相等则跳if_icmpne/if_icmplt/if_icmpge/if_icmpgt/if_icmple0xa0–0xa4v1, v2 →两 int 比较跳转if_acmpeq/if_acmpne0xa5/0xa6v1, v2 →两引用相等/不等则跳ifnull/ifnonnull0xc6/0xc7value →引用为 null/非 null 则跳goto0xa7branch(2B)无条件跳goto_w0xc8branch(4B)无条件跳大范围tableswitch0xaaindex →密集switch第 3 章讲过的「快表」lookupswitch0xabindex →稀疏switch排序键值对jsr/jsr_w/ret0xa8/0xc9/0xa9—旧版子例程finally 用已弃用对应第 2 章returnAddress第 3 章的while循环就是「底部测试 goto跳过首轮」模式switch按密集度选tableswitch/lookupswitch。9. 方法调用与返回Method Invocation / Return指令opcode格式操作数栈说明invokevirtual0xb6index(2B)objref, [args] → result实例虚方法按实际类型分派invokespecial0xb7index(2B)objref, [args] → result父类方法/init/私有方法invokestatic0xb8index(2B)[args] → result静态方法invokeinterface0xb9index,count,0objref, [args] → result接口方法invokedynamic0xbaindex,0,0[args] → result动态调用lambda/引导方法§5.4.3.6ireturn0xacvalue → [empty]返回 intlreturn/freturn/dreturn0xad–0xafvalue →返回 long/float/doubleareturn0xb0value →返回引用return0xb1→ [empty]返回 void四个invoke*的区别是第 3 章的重点invokespecial调init、invokestatic调静态、invokevirtual调普通实例方法、invokeinterface调接口。调用前参数和objref须按描述符顺序在栈上排好。10. 异常与同步Throwing / Synchronization指令opcode操作数栈说明athrow0xbfobjectref → objectref抛出异常第 3 章构造 Throwable 后athrowmonitorenter0xc2objectref →进入对象监视器加锁monitorexit0xc3objectref →退出对象监视器解锁synchronized块编译为monitorentermonitorexit并用异常表保证异常时也解锁。athrow的异常处理由Code里的异常表指引。11. 其他指令opcode说明nop0x00空操作占位/对齐wide0xc4扩展后续指令操作数为 2 字节12. 一个综合例子拆解x a b源码voidadd(){intxab;// 假设 a, b 是 int 字段x 是局部变量}javap -c可能这样反汇编概念示意0: aload_0 // 压入 this字段在对象上 1: getfield #2 // 取字段 a 压栈 4: aload_0 // 压入 this 5: getfield #3 // 取字段 b 压栈 8: iadd // 弹出 a,b压入 ab 9: istore_1 // 存到局部变量 x槽 1对应 opcode 流0x2a 0xb4 0x?? 0x2a 0xb4 0x?? 0x60 0x3c——0x2aaload_00xb4getfield0x60iadd0x3cistore_1。13. 动手用javap -c把玩真实字节码写个含循环、分支、异常的小方法publicclassBytecode{publicstaticintsum(intn){ints0;for(inti1;in;i)si;returns;}}javac Bytecode.java javap-cBytecode.class小结指令 1 字节 opcode 可选操作数长度可变操作数多从栈取记法统一mnemonic opcode 十六进制 栈图 异常按前缀分族i/l/f/d/aload/store/const/add...同一类操作 opcode 连续编号long/double占栈一项2 字宽iinc是唯一原地改局部变量的算术指令new/dup/invokespecial init是对象创建固定三件套。

相关新闻

MiniMax H3 + 本地开源工作流:零基础跑通音乐数字人视频全流程

MiniMax H3 + 本地开源工作流:零基础跑通音乐数字人视频全流程

MiniMax H3 这类音乐生成模型,配合本地开源的数字人工作流,最近我把一条从零到一的流程完整跑通了一遍。结论先说:0基础用户不需要先把深度学习和图形学都学完,也能做出能用的音乐数字人视频;但如果目标是影视剧制作级…

2026/11/2 19:08:17 阅读更多 →
拆解《抓包高冷校花》:校园爽文写作的冲突与反转技巧

拆解《抓包高冷校花》:校园爽文写作的冲突与反转技巧

抓包高冷校花当众嘲笑我身高——这个标题放在任何小说平台上,都属于那种一眼就知道“有点东西”的类型。它同时撞中了校园、高冷女主、误会型冲突、反转和解四个高频卖点。很多新人作者想知道这类爽文到底怎么写,或者为什么自己写出来的情节不吸引人。其…

2026/11/7 22:14:47 阅读更多 →
把意图变成工具:智能体错位追踪的工程实践

把意图变成工具:智能体错位追踪的工程实践

在智能体应用走向复杂化的今天,“模型答错题”已经不再是唯一的问题。真正让人头疼的是另一个更隐蔽的现象:智能体在自主执行多步任务时,会一步一步偏离用户的真实意图,并且整个过程看起来都毫无异常。等开发者发现时,…

2026/11/9 10:08:47 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/13 5:13:25 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/13 5:13:25 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/13 5:13:25 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/13 22:08:41 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/12 18:22:25 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/13 5:13:25 阅读更多 →

日新闻

周新闻

月新闻