Appearance
第6章 Java虚拟机指令集
提示
来自deepseek解释
原文链接:https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-6.html
Java虚拟机指令由一个操作码(opcode)和紧随其后的零个或多个操作数(operands)组成,操作码指定要执行的操作,操作数承载要操作的值。本章详细说明每条Java虚拟机指令的格式及其执行的操作。
6.1 假设:“必须”的含义
每条指令的描述都是在满足第4章(class文件格式)静态和结构约束的Java虚拟机代码上下文中给出的。在描述单个Java虚拟机指令时,我们经常说明某种情况“必须”或“不得”成立:“value2必须是int类型。”第4章(class文件格式)的约束保证了所有这些预期实际上都会得到满足。如果在运行时某条指令描述中的某个约束(“必须”或“不得”)未被满足,则Java虚拟机的行为是未定义的。
Java虚拟机在链接时使用class文件验证器(§4.10)检查Java虚拟机代码是否满足静态和结构约束。因此,Java虚拟机只会尝试执行来自有效class文件的代码。在链接时执行验证很有吸引力,因为检查只执行一次,大大减少了运行时必须完成的工作量。只要符合《Java语言规范(Java SE 17版)》和《Java虚拟机规范(Java SE 17版)》,其他实现策略也是可行的。
6.2 保留操作码
除了本章后面指定的、在class文件(§4(class文件格式))中使用的指令操作码之外,还有三个操作码保留供Java虚拟机实现内部使用。如果将来扩展Java虚拟机的指令集,这些保留操作码保证不会被使用。
其中两个保留操作码,编号254(0xfe)和255(0xff),其助记符分别为impdep1和impdep2。这些指令旨在提供“后门”或陷阱,分别用于实现特定于软件和硬件的功能。第三个保留操作码,编号202(0xca),其助记符为breakpoint,旨在供调试器用于实现断点。
尽管这些操作码已被保留,但它们只能在Java虚拟机实现内部使用。它们不能出现在有效的class文件中。诸如调试器或JIT代码生成器(§2.13)等可能直接与已加载和执行的Java虚拟机代码交互的工具可能会遇到这些操作码。如果遇到任何这些保留指令,此类工具应尝试优雅地处理。
6.3 虚拟机错误
当内部错误或资源限制阻止Java虚拟机实现本章描述的语义时,Java虚拟机实现会抛出VirtualMachineError类的子类的实例。本规范无法预测可能在何处遇到内部错误或资源限制,也没有规定何时必须报告它们。因此,下面定义的任何VirtualMachineError子类都可以在Java虚拟机运行期间的任何时间抛出:
InternalError:Java虚拟机实现中发生了内部错误,原因可能是实现虚拟机的软件有缺陷、底层主机系统软件有缺陷或硬件有缺陷。此错误在检测到时异步(§2.10)传递,并且可能发生在程序的任何时刻。OutOfMemoryError:Java虚拟机实现已耗尽虚拟内存或物理内存,并且自动存储管理器无法回收足够的内存来满足对象创建请求。StackOverflowError:Java虚拟机实现已耗尽线程的栈空间,通常是因为执行程序中的错误导致线程进行了无限次数的递归调用。UnknownError:发生了异常或错误,但Java虚拟机实现无法报告实际的异常或错误。
6.4 指令描述的格式
本章中的Java虚拟机指令按字母顺序排列,每条指令以如下所示的条目形式表示,并各自从新的一页开始。
指令格式图中的每个单元格代表一个8位字节。指令的助记符(mnemonic)是其名称。其操作码是它的数字表示,以十进制和十六进制两种形式给出。在class文件的Java虚拟机代码中实际存在的只有数字表示。
请记住,既有编译时生成并嵌入Java虚拟机指令中的“操作数”,也有运行时计算并在操作数栈上提供的“操作数”。尽管它们来自几个不同的区域,但所有这些操作数都代表同一件事:正在执行的Java虚拟机指令要操作的值。通过隐式地从其操作数栈中获取许多操作数,而不是在编译代码中将它们显式表示为额外的操作数字节、寄存器编号等,Java虚拟机的代码保持了紧凑性。
某些指令作为相关指令家族(family)的成员呈现,共享单个描述、格式和操作数栈图。因此,一个指令家族包含多个操作码和操作码助记符;只有家族助记符出现在指令格式图中,并且一个单独的forms行列出了所有成员助记符和操作码。例如,lconst_<l>指令家族的Forms行给出了该家族中两条指令(lconst_0和lconst_1)的助记符和操作码信息:
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)在Java虚拟机指令的描述中,指令执行对当前帧(§2.6)的操作数栈(§2.6.2)的影响以文本方式表示,栈从左到右增长,每个值单独表示。因此,
..., value1, value2 → ..., result表示一个操作,该操作开始时value2在操作数栈的顶部,value1在其下方。作为指令执行的结果,value1和value2从操作数栈弹出,并被指令计算出的结果值result替换。操作数栈的其余部分(用省略号(...)表示)不受指令执行的影响。
long和double类型的值在操作数栈上由单个条目表示。在《Java®虚拟机规范》第一版中,long和double类型的值在栈图中各由两个条目表示。
6.5 指令
aaload
操作:从数组加载引用
格式:aaload
形式:aaload = 50 (0x32)
操作数栈:
..., arrayref, index → ..., value描述:arrayref必须是reference类型,并且必须引用一个组件类型为reference的数组。index必须是int类型。arrayref和index从操作数栈弹出。数组中index位置的引用值被取出并压入操作数栈。
运行时异常:
- 如果
arrayref为null,aaload抛出NullPointerException。 - 否则,如果
index不在arrayref引用的数组边界内,aaload抛出ArrayIndexOutOfBoundsException。
aastore
操作:存储到引用数组
格式:aastore
形式:aastore = 83 (0x53)
操作数栈:
..., arrayref, index, value → ...描述:arrayref必须是reference类型,并且必须引用一个组件类型为reference的数组。index必须是int类型,value必须是reference类型。arrayref、index和value从操作数栈弹出。
如果value为null,则将其存储为数组中index位置的组件。
否则,value非空。如果value的类型与arrayref引用的数组组件类型赋值兼容,则将value存储为数组中index位置的组件。
确定非空值与数组组件类型赋值兼容性的规则如下(S为value所指对象的类型,T为数组组件的引用类型):
- 如果S是类类型:
- 如果T是类类型,则S必须与T相同,或是T的子类;
- 如果T是接口类型,则S必须实现接口T。
- 如果S是数组类型SC[](组件类型为SC的数组):
- 如果T是类类型,则T必须是
Object。 - 如果T是接口类型,则T必须是数组实现的接口之一(JLS §4.10.3)。
- 如果T是数组类型TC[],则以下之一必须成立:
- TC和SC是相同的原始类型;
- TC和SC是引用类型,且SC类型可通过这些运行时规则赋值给TC。
- 如果T是类类型,则T必须是
运行时异常:
- 如果
arrayref为null,aastore抛出NullPointerException。 - 否则,如果
index不在数组边界内,抛出ArrayIndexOutOfBoundsException。 - 否则,如果非空值的实际类型与数组组件的实际类型不兼容,抛出
ArrayStoreException。
aconst_null
操作:压入null
格式:aconst_null
形式:aconst_null = 1 (0x1)
操作数栈:
... → ..., null描述:将null对象引用压入操作数栈。
注意:Java虚拟机不强制规定null的具体值。
aload
操作:从局部变量加载引用
格式:aload index
形式:aload = 25 (0x19)
操作数栈:
... → ..., objectref描述:index是一个无符号字节,必须是当前帧(§2.6)局部变量数组的索引。index处的局部变量必须包含一个引用。该局部变量中的objectref被压入操作数栈。
注意:aload指令不能用于将returnAddress类型的值从局部变量加载到操作数栈。这种与astore指令(§astore)的不对称是有意设计的。aload操作码可与wide指令(§wide)一起使用,通过两字节无符号索引访问局部变量。
aload_<n>
操作:从局部变量加载引用
格式:aload_<n>
形式:
aload_0 = 42 (0x2a)
aload_1 = 43 (0x2b)
aload_2 = 44 (0x2c)
aload_3 = 45 (0x2d)操作数栈:
... → ..., objectref描述:<n>必须是当前帧局部变量数组的索引。<n>处的局部变量必须包含一个引用。该局部变量中的objectref被压入操作数栈。
注意:aload_<n>指令不能用于加载returnAddress类型值。每条aload_<n>指令等同于aload且索引为<n>,只是操作数<n>是隐式的。
anewarray
操作:创建新的引用数组
格式:anewarray indexbyte1 indexbyte2
形式:anewarray = 189 (0xbd)
操作数栈:
..., count → ..., arrayref描述:count必须是int类型,从操作数栈弹出。count表示要创建的数组的组件数量。无符号indexbyte1和indexbyte2用于构造当前类(§2.6)运行时常量池的索引,值为(indexbyte1 << 8) | indexbyte2。该索引处的运行时常量池项必须是对类、数组或接口类型的符号引用。命名类型被解析(§5.4.3.1)。从垃圾收集堆中分配一个长度为count、组件类型为该类型的新数组,并将引用arrayref压入操作数栈。新数组的所有组件初始化为null(引用类型的默认值)。
链接异常:解析符号引用期间可能抛出§5.4.3.1中记录的任何异常。
运行时异常:如果count小于零,抛出NegativeArraySizeException。
注意:用于创建对象引用数组的一维或多维数组的一部分。
areturn
操作:从方法返回引用
格式:areturn
形式:areturn = 176 (0xb0)
操作数栈:
..., objectref → [empty]描述:objectref必须是reference类型,且引用的对象类型必须与当前方法的返回描述符(§4.3.3)所表示的类型赋值兼容。如果当前方法是synchronized方法,则在当前线程中如同执行monitorexit指令(§monitorexit)一样更新并可能退出在方法调用时进入或重入的监视器。如果未抛出异常,objectref从当前帧(§2.6)的操作数栈弹出,并压入调用者帧的操作数栈。当前方法操作数栈上的任何其他值被丢弃。解释器随后恢复调用者的帧并将控制权返回给调用者。
运行时异常:
- 如果Java虚拟机实现不强制结构化锁定规则(§2.11.10),且当前方法是
synchronized方法,而当前线程不是方法调用时进入或重入的监视器的所有者,则抛出IllegalMonitorStateException(例如,同步方法中包含monitorexit但无monitorenter)。 - 如果实现强制结构化锁定规则且第一条规则在调用当前方法期间被违反,则抛出
IllegalMonitorStateException。
arraylength
操作:获取数组长度
格式:arraylength
形式:arraylength = 190 (0xbe)
操作数栈:
..., arrayref → ..., length描述:arrayref必须是reference类型且必须引用一个数组。它从操作数栈弹出。确定其所引用数组的长度,并将该长度作为int压入操作数栈。
运行时异常:如果arrayref为null,抛出NullPointerException。
astore
操作:将引用存储到局部变量
格式:astore index
形式:astore = 58 (0x3a)
操作数栈:
..., objectref → ...描述:index是无符号字节,必须是当前帧局部变量数组的索引。操作数栈顶的objectref必须是returnAddress或reference类型。它从操作数栈弹出,并将index处的局部变量设置为objectref。
注意:astore用于在实现finally子句时存储returnAddress类型值。aload不能加载returnAddress。可与wide配合使用。
astore_<n>
操作:将引用存储到局部变量
格式:astore_<n>
形式:
astore_0 = 75 (0x4b)
astore_1 = 76 (0x4c)
astore_2 = 77 (0x4d)
astore_3 = 78 (0x4e)操作数栈:
..., objectref → ...描述:<n>必须是局部变量数组索引。栈顶的objectref必须是returnAddress或reference类型,弹出后设置局部变量<n>。
注意:每条astore_<n>等同于astore且索引为<n>,操作数隐式。
athrow
操作:抛出异常或错误
格式:athrow
形式:athrow = 191 (0xbf)
操作数栈:
..., objectref → objectref描述:objectref必须是reference类型,且引用的对象必须是Throwable或其子类的实例。它从操作数栈弹出,然后通过在当前方法(§2.6)中搜索与objectref类匹配的第一个异常处理器来抛出(算法见§2.10)。如果找到匹配的处理器,则重置PC到该位置,清除当前帧的操作数栈,将objectref压回栈,继续执行。如果当前帧中未找到匹配处理器,则弹出该帧。如果当前帧代表同步方法的调用,则如同执行monitorexit退出监视器。最后恢复调用者帧(如果存在)并重新抛出objectref;若不存在,则当前线程退出。
运行时异常:
- 如果
objectref为null,抛出NullPointerException(而不是objectref)。 - 如果实现不强制结构化锁定且当前方法为同步方法且线程不是监视器所有者,则抛出
IllegalMonitorStateException(替代原抛出对象)。 - 如果实现强制结构化锁定且第一条规则违反,同样抛出
IllegalMonitorStateException。
注意:栈图可能误导:若在当前方法中匹配到处理器,athrow丢弃所有栈值并压入抛出对象;若未匹配,则栈被清空,对象压入处理方法的空栈。
baload
操作:从数组加载byte或boolean
格式:baload
形式:baload = 51 (0x33)
操作数栈:
..., arrayref, index → ..., value描述:arrayref必须引用组件类型为byte或boolean的数组。index为int。弹出两者,取出组件值,符号扩展为int并压栈。
运行时异常:同aaload。
bastore
操作:存储到byte或boolean数组
格式:bastore
形式:bastore = 84 (0x54)
操作数栈:
..., arrayref, index, value → ...描述:arrayref引用byte或boolean数组,index和value为int。弹出三者。若为byte数组,value截断为byte存储;若为boolean数组,将value与1按位与后存储。
运行时异常:同aastore。
bipush
操作:压入byte
格式:bipush byte
形式:bipush = 16 (0x10)
操作数栈:
... → ..., value描述:立即byte符号扩展为int值并压栈。
caload
操作:从数组加载char
格式:caload
形式:caload = 52 (0x34)
操作数栈:
..., arrayref, index → ..., value描述:arrayref引用char数组,index为int。取出组件值,零扩展为int并压栈。
运行时异常:同aaload。
castore
操作:存储到char数组
格式:castore
形式:castore = 85 (0x55)
操作数栈:
..., arrayref, index, value → ...描述:arrayref引用char数组,index和value为int。value截断为char存储。
运行时异常:同aastore。
checkcast
操作:检查对象是否为给定类型
格式:checkcast indexbyte1 indexbyte2
形式:checkcast = 192 (0xc0)
操作数栈:
..., objectref → ..., objectref描述:objectref为reference。构造常量池索引,解析类型。若objectref为null,栈不变;否则,若可转换为解析类型,栈不变;否则抛出ClassCastException。转换规则与instanceof相同。
链接异常:解析期间可抛出§5.4.3.1中的异常。
运行时异常:若不能转换,抛出ClassCastException。
注意:与instanceof类似,但处理null和失败行为不同。
d2f
操作:将double转换为float
格式:d2f
形式:d2f = 144 (0x90)
操作数栈:
..., value → ..., result描述:栈顶value为double,弹出并使用向最近舍入(§2.8)转换为float结果压栈。太小则转为同号零,太大转为同号无穷大,double NaN转为float NaN。
注意:窄化转换,可能丢失精度。
d2i
操作:将double转换为int
格式:d2i
形式:d2i = 142 (0x8e)
操作数栈:
..., value → ..., result描述:栈顶double弹出,转换为int:
- 若为NaN,结果为0;
- 否则若非无穷,使用向零舍入得到整数值V,若可表示为
int则结果为V; - 否则太小或太负,结果为
int的最小或最大值。
注意:窄化转换,可能丢失精度和符号。
d2l
操作:将double转换为long
格式:d2l
形式:d2l = 143 (0x8f)
操作数栈:
..., value → ..., result描述:类似d2i,但结果为long。
dadd
操作:double加法
格式:dadd
形式:dadd = 99 (0x63)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个double,计算value1 + value2,结果压栈。遵循IEEE 754规则(NaN、无穷、零、溢出、下溢等)。支持渐进下溢。从不抛出运行时异常。
daload
操作:从数组加载double
格式:daload
形式:daload = 49 (0x31)
操作数栈:
..., arrayref, index → ..., value描述:arrayref引用double数组,index为int。取出double值压栈。
运行时异常:同aaload。
dastore
操作:存储到double数组
格式:dastore
形式:dastore = 82 (0x52)
操作数栈:
..., arrayref, index, value → ...描述:arrayref引用double数组,index和value为double。存储value。
运行时异常:同aastore。
dcmp<op>
操作:比较double
格式:dcmp<op>
形式:
dcmpg = 152 (0x98)
dcmpl = 151 (0x97)操作数栈:
..., value1, value2 → ..., result描述:弹出两个double,比较:
- 若
value1 > value2,压入1; - 若相等,压入0;
- 若
value1 < value2,压入-1; - 若任一为NaN,
dcmpg压入1,dcmpl压入-1。
遵循IEEE 754有序比较。
注意:两者仅在NaN处理上不同。
dconst_<d>
操作:压入double常量
格式:dconst_<d>
形式:
dconst_0 = 14 (0xe)
dconst_1 = 15 (0xf)操作数栈:
... → ..., <d>描述:压入0.0或1.0。
ddiv
操作:double除法
格式:ddiv
形式:ddiv = 111 (0x6f)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 / value2,遵循IEEE 754(NaN、无穷、零、符号规则)。支持渐进下溢。从不抛出运行时异常。
dload
操作:从局部变量加载double
格式:dload index
形式:dload = 24 (0x18)
操作数栈:
... → ..., value描述:index和index+1必须是有效索引。局部变量index处为double,将其值压栈。
注意:可与wide配合。
dload_<n>
操作:从局部变量加载double
格式:dload_<n>
形式:
dload_0 = 38 (0x26)
dload_1 = 39 (0x27)
dload_2 = 40 (0x28)
dload_3 = 41 (0x29)操作数栈:
... → ..., value描述:<n>和<n>+1为索引,加载double值。
dmul
操作:double乘法
格式:dmul
形式:dmul = 107 (0x6b)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 * value2,遵循IEEE 754。支持渐进下溢,从不抛出异常。
dneg
操作:double取反
格式:dneg
形式:dneg = 119 (0x77)
操作数栈:
..., value → ..., result描述:弹出double,计算算术取反。对于NaN,结果仍为NaN(不反转符号位)。无穷和零取反改变符号。
注意:未采用IEEE 754 2019版要求反转NaN符号位的更强要求。
drem
操作:double取余
格式:drem
形式:drem = 115 (0x73)
操作数栈:
..., value1, value2 → ..., result描述:计算余数,不同于IEEE 754余数(因舍入策略不同)。Java虚拟机定义drem行为类似于整数余数,隐含使用向零舍入的除法(类似C的fmod)。规则:
- NaN则NaN;
- 符号与被除数相同;
- 被除数为无穷或除数为零则NaN;
- 被除数有限除数无穷则结果等于被除数;
- 被除数为零除数有限则结果等于被除数;
- 否则
result = value1 - (value2 * q),其中q为整数,符号与value1/value2相同,且其绝对值尽可能大而不超过真实商。 - 从不抛出异常(除零不会抛出)。
注意:IEEE 754余数可通过Math.IEEEremainder计算。
dreturn
操作:从方法返回double
格式:dreturn
形式:dreturn = 175 (0xaf)
操作数栈:
..., value → [empty]描述:当前方法返回类型为double,弹出value,压入调用者栈。同步方法处理监视器。
运行时异常:同areturn中的结构化锁定异常。
dstore
操作:将double存储到局部变量
格式:dstore index
形式:dstore = 57 (0x39)
操作数栈:
..., value → ...描述:index和index+1为索引,栈顶double弹出,存储到index和index+1。
注意:可与wide配合。
dstore_<n>
操作:将double存储到局部变量
格式:dstore_<n>
形式:
dstore_0 = 71 (0x47)
dstore_1 = 72 (0x48)
dstore_2 = 73 (0x49)
dstore_3 = 74 (0x4a)操作数栈:
..., value → ...描述:<n>和<n>+1索引,存储double。
dsub
操作:double减法
格式:dsub
形式:dsub = 103 (0x67)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 - value2。遵循IEEE 754,a-b等同于a+(-b),但0.0 - x不等于-x(正零情况)。支持渐进下溢,从不抛出异常。
dup
操作:复制栈顶值
格式:dup
形式:dup = 89 (0x59)
操作数栈:
..., value → ..., value, value描述:复制栈顶值(类别1计算类型)并压入。
dup_x1
操作:复制栈顶值并插入到两个值之下
格式:dup_x1
形式:dup_x1 = 90 (0x5a)
操作数栈:
..., value2, value1 → ..., value1, value2, value1描述:复制栈顶value1,插入到value2之下。两个值都必须是类别1类型。
dup_x2
操作:复制栈顶值并插入到两个或三个值之下
格式:dup_x2
形式:dup_x2 = 91 (0x5b)
操作数栈:
- 形式1:
..., value3, value2, value1 → ..., value1, value3, value2, value1(全部类别1) - 形式2:
..., value2, value1 → ..., value1, value2, value1(value1类别1,value2类别2)
描述:复制栈顶value1,插入到下面两个或三个值之下,取决于下面值的类别。
dup2
操作:复制栈顶一个或两个值
格式:dup2
形式:dup2 = 92 (0x5c)
操作数栈:
- 形式1:
..., value2, value1 → ..., value2, value1, value2, value1(两个类别1) - 形式2:
..., value → ..., value, value(一个类别2)
描述:复制栈顶一个类别2值或两个类别1值,按原顺序压入。
dup2_x1
操作:复制栈顶一个或两个值并插入到两个或三个值之下
格式:dup2_x1
形式:dup2_x1 = 93 (0x5d)
操作数栈:
- 形式1:
..., value3, value2, value1 → ..., value2, value1, value3, value2, value1(全部类别1) - 形式2:
..., value2, value1 → ..., value1, value2, value1(value1类别2,value2类别1)
描述:复制栈顶一个或两个值(value2, value1或单个value1),按原顺序插入到下方。
dup2_x2
操作:复制栈顶一个或两个值并插入到两个、三个或四个值之下
格式:dup2_x2
形式:dup2_x2 = 94 (0x5e)
操作数栈:
- 形式1:
..., value4, value3, value2, value1 → ..., value2, value1, value4, value3, value2, value1(四个类别1) - 形式2:
..., value3, value2, value1 → ..., value1, value3, value2, value1(value1类别2,value2和value3类别1) - 形式3:
..., value3, value2, value1 → ..., value2, value1, value3, value2, value1(value1和value2类别1,value3类别2) - 形式4:
..., value2, value1 → ..., value1, value2, value1(两个类别2)
描述:复制栈顶一个或两个值(value2, value1或单个value1),按原顺序插入到下方适当位置,具体取决于栈中其他值的类别。
f2d
操作:将float转换为double
格式:f2d
形式:f2d = 141 (0x8d)
操作数栈:
..., value → ..., result描述:栈顶的value必须是float类型。它被弹出并转换为double结果,结果压入栈。
注意:f2d执行拓宽原始转换(JLS §5.1.2)。
f2i
操作:将float转换为int
格式:f2i
形式:f2i = 139 (0x8b)
操作数栈:
..., value → ..., result描述:栈顶的value必须是float类型。它被弹出并转换为int结果,结果压入栈:
- 如果
value是NaN,结果为int0。 - 否则,如果
value不是无穷大,则使用向零舍入策略(§2.8)舍入为整数值V。如果V可表示为int,则结果为V。 - 否则,
value太小(负大值或负无穷)则结果为int的最小值;太大(正大值或正无穷)则结果为int的最大值。
注意:执行窄化原始转换(JLS §5.1.3),可能丢失幅值和精度。
f2l
操作:将float转换为long
格式:f2l
形式:f2l = 140 (0x8c)
操作数栈:
..., value → ..., result描述:类似f2i,但结果为long。NaN为0,向零舍入,超出范围则取long的最小或最大值。
注意:窄化原始转换。
fadd
操作:float加法
格式:fadd
形式:fadd = 98 (0x62)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个float,计算value1 + value2,结果压栈。遵循IEEE 754规则(NaN、无穷、零、溢出、下溢)。支持渐进下溢。从不抛出运行时异常。
faload
操作:从数组加载float
格式:faload
形式:faload = 48 (0x30)
操作数栈:
..., arrayref, index → ..., value描述:arrayref必须引用组件类型为float的数组,index为int。取出float值压栈。
运行时异常:同aaload。
fastore
操作:存储到float数组
格式:fastore
形式:fastore = 81 (0x51)
操作数栈:
..., arrayref, index, value → ...描述:arrayref引用float数组,index为int,value为float。存储。
运行时异常:同aastore。
fcmp<op>
操作:比较float
格式:fcmp<op>
形式:
fcmpg = 150 (0x96)
fcmpl = 149 (0x95)操作数栈:
..., value1, value2 → ..., result描述:弹出两个float进行比较:
- 若
value1 > value2,压入1; - 若相等,压入0;
- 若
value1 < value2,压入-1; - 若任一为NaN,
fcmpg压入1,fcmpl压入-1。
遵循IEEE 754有序比较。
注意:两者仅在NaN处理上不同。
fconst_<f>
操作:压入float常量
格式:fconst_<f>
形式:
fconst_0 = 11 (0xb)
fconst_1 = 12 (0xc)
fconst_2 = 13 (0xd)操作数栈:
... → ..., <f>描述:压入0.0、1.0或2.0。
fdiv
操作:float除法
格式:fdiv
形式:fdiv = 110 (0x6e)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 / value2,遵循IEEE 754。支持渐进下溢,从不抛出运行时异常。
fload
操作:从局部变量加载float
格式:fload index
形式:fload = 23 (0x17)
操作数栈:
... → ..., value描述:index为局部变量索引,加载float值压栈。
注意:可与wide配合。
fload_<n>
操作:从局部变量加载float
格式:fload_<n>
形式:
fload_0 = 34 (0x22)
fload_1 = 35 (0x23)
fload_2 = 36 (0x24)
fload_3 = 37 (0x25)操作数栈:
... → ..., value描述:<n>为索引,加载float。
fmul
操作:float乘法
格式:fmul
形式:fmul = 106 (0x6a)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 * value2,遵循IEEE 754。支持渐进下溢,从不抛出异常。
fneg
操作:float取反
格式:fneg
形式:fneg = 118 (0x76)
操作数栈:
..., value → ..., result描述:弹出float,计算算术取反。NaN仍为NaN(不反转符号位)。无穷和零改变符号。
注意:未采用IEEE 754 2019版要求反转NaN符号位的更强要求。
frem
操作:float取余
格式:frem
形式:frem = 114 (0x72)
操作数栈:
..., value1, value2 → ..., result描述:计算余数,类似drem,但针对float。使用向零舍入的隐含除法(类似fmod)。规则同drem。从不抛出异常。
注意:IEEE 754余数可通过Math.IEEEremainder计算。
freturn
操作:从方法返回float
格式:freturn
形式:freturn = 174 (0xae)
操作数栈:
..., value → [empty]描述:当前方法返回类型为float,弹出value压入调用者栈。同步方法处理监视器。
运行时异常:同areturn中的结构化锁定异常。
fstore
操作:将float存储到局部变量
格式:fstore index
形式:fstore = 56 (0x38)
操作数栈:
..., value → ...描述:index为局部变量索引,弹出栈顶float,存储到index。
注意:可与wide配合。
fstore_<n>
操作:将float存储到局部变量
格式:fstore_<n>
形式:
fstore_0 = 67 (0x43)
fstore_1 = 68 (0x44)
fstore_2 = 69 (0x45)
fstore_3 = 70 (0x46)操作数栈:
..., value → ...描述:<n>为索引,存储float。
fsub
操作:float减法
格式:fsub
形式:fsub = 102 (0x66)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 - value2。遵循IEEE 754,a-b等同于a+(-b),但0.0 - x不等于-x。支持渐进下溢,从不抛出异常。
getfield
操作:从对象中获取字段
格式:getfield indexbyte1 indexbyte2
形式:getfield = 180 (0xb4)
操作数栈:
..., objectref → ..., value描述:构造常量池索引,解析字段引用(§5.4.3.2)。弹出objectref(非数组引用),取出字段值压栈。
链接异常:字段解析可能抛出§5.4.3.2中的错误;若解析字段是静态字段,抛出IncompatibleClassChangeError。
运行时异常:若objectref为null,抛出NullPointerException。
注意:不能用于数组的length字段,应使用arraylength。
getstatic
操作:从类获取静态字段
格式:getstatic indexbyte1 indexbyte2
形式:getstatic = 178 (0xb2)
操作数栈:
... → ..., value描述:构造常量池索引,解析字段引用。成功解析后,初始化声明该字段的类或接口(若未初始化)。获取字段值压栈。
链接异常:字段解析错误;若解析字段不是静态字段,抛出IncompatibleClassChangeError。
运行时异常:若初始化导致错误,可能抛出Error(详见§5.5)。
goto
操作:无条件跳转
格式:goto branchbyte1 branchbyte2
形式:goto = 167 (0xa7)
操作数栈:无变化
描述:构造16位有符号偏移(branchbyte1 << 8) | branchbyte2,从当前指令地址跳转,目标必须为方法内指令操作码地址。
goto_w
操作:无条件跳转(宽索引)
格式:goto_w branchbyte1 branchbyte2 branchbyte3 branchbyte4
形式:goto_w = 200 (0xc8)
操作数栈:无变化
描述:构造32位有符号偏移,跳转。目标必须为方法内指令。
注意:虽然偏移为4字节,但方法大小受限于65535字节(§4.11)。
i2b
操作:将int转换为byte
格式:i2b
形式:i2b = 145 (0x91)
操作数栈:
..., value → ..., result描述:弹出int,截断为byte,符号扩展为int压栈。
注意:窄化转换,可能丢失信息。
i2c
操作:将int转换为char
格式:i2c
形式:i2c = 146 (0x92)
操作数栈:
..., value → ..., result描述:弹出int,截断为char,零扩展为int压栈。
i2d
操作:将int转换为double
格式:i2d
形式:i2d = 135 (0x87)
操作数栈:
..., value → ..., result描述:弹出int,转换为double(精确,因为所有int值可精确表示)。
注意:拓宽转换。
i2f
操作:将int转换为float
格式:i2f
形式:i2f = 134 (0x86)
操作数栈:
..., value → ..., result描述:弹出int,使用向最近舍入转换为float,可能丢失精度(float仅有24位有效数)。
注意:拓宽转换但可能损失精度。
i2l
操作:将int转换为long
格式:i2l
形式:i2l = 133 (0x85)
操作数栈:
..., value → ..., result描述:弹出int,符号扩展为long(精确)。
注意:拓宽转换。
i2s
操作:将int转换为short
格式:i2s
形式:i2s = 147 (0x93)
操作数栈:
..., value → ..., result描述:弹出int,截断为short,符号扩展为int。
注意:窄化转换。
iadd
操作:int加法
格式:iadd
形式:iadd = 96 (0x60)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个int,计算和,取低32位作为结果。溢出时结果符号可能与数学和不同,但不抛出异常。
iaload
操作:从数组加载int
格式:iaload
形式:iaload = 46 (0x2e)
操作数栈:
..., arrayref, index → ..., value描述:arrayref引用int数组,index为int,取出int值压栈。
运行时异常:同aaload。
iand
操作:int按位与
格式:iand
形式:iand = 126 (0x7e)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个int,按位与后压栈。
iastore
操作:存储到int数组
格式:iastore
形式:iastore = 79 (0x4f)
操作数栈:
..., arrayref, index, value → ...描述:arrayref引用int数组,index和value为int,存储。
运行时异常:同aastore。
iconst_<i>
操作:压入int常量
格式:iconst_<i>
形式:
iconst_m1 = 2 (0x2)
iconst_0 = 3 (0x3)
iconst_1 = 4 (0x4)
iconst_2 = 5 (0x5)
iconst_3 = 6 (0x6)
iconst_4 = 7 (0x7)
iconst_5 = 8 (0x8)操作数栈:
... → ..., <i>描述:压入-1、0、1、2、3、4或5。
idiv
操作:int除法
格式:idiv
形式:idiv = 108 (0x6c)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 / value2,向零舍入。特殊:若被除数为int最小值且除数为-1,则结果为被除数(溢出但不抛异常)。
运行时异常:若除数为0,抛出ArithmeticException。
if_acmp<cond>
操作:引用比较成功则跳转
格式:if_acmp<cond> branchbyte1 branchbyte2
形式:
if_acmpeq = 165 (0xa5)
if_acmpne = 166 (0xa6)操作数栈:
..., value1, value2 → ...描述:弹出两个reference比较,if_acmpeq在相等时跳转,if_acmpne在不相等时跳转。构造16位偏移,跳转到目标;否则执行下一条。
if_icmp<cond>
操作:int比较成功则跳转
格式:if_icmp<cond> branchbyte1 branchbyte2
形式:
if_icmpeq = 159 (0x9f)
if_icmpne = 160 (0xa0)
if_icmplt = 161 (0xa1)
if_icmpge = 162 (0xa2)
if_icmpgt = 163 (0xa3)
if_icmple = 164 (0xa4)操作数栈:
..., value1, value2 → ...描述:弹出两个int,根据条件(==、≠、<、≤、>、≥)跳转。
if<cond>
操作:int与零比较成功则跳转
格式:if<cond> branchbyte1 branchbyte2
形式:
ifeq = 153 (0x99)
ifne = 154 (0x9a)
iflt = 155 (0x9b)
ifge = 156 (0x9c)
ifgt = 157 (0x9d)
ifle = 158 (0x9e)操作数栈:
..., value → ...描述:弹出int,与零比较(==、≠、<、≥、>、≤),满足则跳转。
ifnonnull
操作:引用非空则跳转
格式:ifnonnull branchbyte1 branchbyte2
形式:ifnonnull = 199 (0xc7)
操作数栈:
..., value → ...描述:弹出reference,若非null则跳转。
ifnull
操作:引用为空则跳转
格式:ifnull branchbyte1 branchbyte2
形式:ifnull = 198 (0xc6)
操作数栈:
..., value → ...描述:弹出reference,若为null则跳转。
iinc
操作:局部变量增加常量
格式:iinc index const
形式:iinc = 132 (0x84)
操作数栈:无变化
描述:index为局部变量索引,const为有符号字节,扩展为int,将局部变量int值增加该量。
注意:可与wide配合使用两字节索引和两字节增量。
iload
操作:从局部变量加载int
格式:iload index
形式:iload = 21 (0x15)
操作数栈:
... → ..., value描述:加载int局部变量。
注意:可与wide配合。
iload_<n>
操作:从局部变量加载int
格式:iload_<n>
形式:
iload_0 = 26 (0x1a)
iload_1 = 27 (0x1b)
iload_2 = 28 (0x1c)
iload_3 = 29 (0x1d)操作数栈:
... → ..., value描述:<n>为索引,加载int。
imul
操作:int乘法
格式:imul
形式:imul = 104 (0x68)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 * value2,取低32位。溢出不抛异常。
ineg
操作:int取反
格式:ineg
形式:ineg = 116 (0x74)
操作数栈:
..., value → ..., result描述:计算-value。对最大负数取反仍为自身(溢出不抛异常)。
instanceof
操作:确定对象是否为给定类型
格式:instanceof indexbyte1 indexbyte2
形式:instanceof = 193 (0xc1)
操作数栈:
..., objectref → ..., result描述:弹出objectref,解析类型。若为null压入0;否则若是指定类型的实例压入1,否则0。转换规则与checkcast相同。
链接异常:解析异常。
注意:与checkcast区别在于处理null和失败行为。
invokedynamic
操作:调用动态计算调用点
格式:invokedynamic indexbyte1 indexbyte2 0 0
形式:invokedynamic = 186 (0xba)
操作数栈:
..., [arg1, [arg2 ...]] → ...描述:解析动态调用点符号引用(§5.4.3.6)得到CallSite,绑定到该指令。然后调用目标方法句柄,如同invokevirtual调用MethodHandle.invokeExact。
链接异常:解析期间异常。
注意:若解析成功,则目标非空且方法类型匹配,不会抛出NullPointerException或WrongMethodTypeException。
invokeinterface
操作:调用接口方法
格式:invokeinterface indexbyte1 indexbyte2 count 0
形式:invokeinterface = 185 (0xb9)
操作数栈:
..., objectref, [arg1, [arg2 ...]] → ...描述:解析接口方法引用(§5.4.3.4)。count表示参数大小(必须非零)。根据objectref的类选择方法(§5.4.6)。如果是同步方法则进入监视器。非本地方法创建新帧传递参数;本地方法绑定并调用。
链接异常:解析错误;若解析方法为静态,抛出IncompatibleClassChangeError。
运行时异常:
objectref为null →NullPointerException。- 类未实现接口 →
IncompatibleClassChangeError。 - 选择的方法不是public或private →
IllegalAccessError。 - 选择抽象方法 →
AbstractMethodError。 - 本地方法无法绑定 →
UnsatisfiedLinkError。 - 多个最具体非抽象方法 →
IncompatibleClassChangeError。 - 无非抽象最具体方法 →
AbstractMethodError。
注意:count冗余,历史原因。第四字节保留。
invokespecial
操作:调用实例方法;直接调用实例初始化方法及当前类及其超类型的方法
格式:invokespecial indexbyte1 indexbyte2
形式:invokespecial = 183 (0xb7)
操作数栈:
..., objectref, [arg1, [arg2 ...]] → ...描述:解析方法引用。若解析方法不是<init>且符号引用命名的是当前类的超类且ACC_SUPER标志设置,则C为当前类的直接超类;否则C为符号引用的类。查找实际方法:在C中查找,若找不到且在类中则沿超类链查找,若在接口中则检查Object的public方法,最后检查最具体超接口方法。调用过程与invokeinterface类似。
链接异常:解析错误;若解析为静态方法抛出IncompatibleClassChangeError;若为<init>且类与符号引用不同则NoSuchMethodError。
运行时异常:objectref为null → NullPointerException;选择抽象方法 → AbstractMethodError;本地无法绑定 → UnsatisfiedLinkError;多个/无最具体非抽象 → IncompatibleClassChangeError/AbstractMethodError。
注意:invokespecial用于调用<init>、super方法等。历史上称invokenonvirtual。
invokestatic
操作:调用类(静态)方法
格式:invokestatic indexbyte1 indexbyte2
形式:invokestatic = 184 (0xb8)
操作数栈:
..., [arg1, [arg2 ...]] → ...描述:解析静态方法引用(§5.4.3.3)。解析后初始化声明类。参数从栈弹出,创建帧或调用本地方法。
链接异常:解析错误;若解析为实例方法抛出IncompatibleClassChangeError。
运行时异常:初始化可能抛出Error;本地无法绑定 → UnsatisfiedLinkError。
invokevirtual
操作:调用实例方法;基于类分派
格式:invokevirtual indexbyte1 indexbyte2
形式:invokevirtual = 182 (0xb6)
操作数栈:
..., objectref, [arg1, [arg2 ...]] → ...描述:解析实例方法引用。若非签名多态方法,则根据objectref的类选择方法(§5.4.6),然后调用(同步、帧创建或本地绑定)。若为签名多态方法(MethodHandle或VarHandle),则特殊处理:对于MethodHandle.invokeExact要求类型精确匹配;invoke允许类型调整;VarHandle方法通过访问模式和方法类型构造调用器方法句柄并调用。
链接异常:解析错误;若解析为静态方法抛出IncompatibleClassChangeError;签名多态方法类型解析异常。
运行时异常:objectref为null → NullPointerException;非签名多态且选择抽象方法 → AbstractMethodError;本地无法绑定 → UnsatisfiedLinkError;多个/无最具体非抽象 → IncompatibleClassChangeError/AbstractMethodError;签名多态类型不匹配 → WrongMethodTypeException。
注意:可能解析到接口方法,选择逻辑与invokeinterface类似。
ior
操作:int按位或
格式:ior
形式:ior = 128 (0x80)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个int,按位或后压栈。
irem
操作:int取余
格式:irem
形式:irem = 112 (0x70)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个int,计算 value1 - (value1 / value2) * value2,结果压栈。满足 (a/b)*b + (a%b) = a。即使被除数为int最小值且除数为-1,余数为0。余数的符号与被除数相同,绝对值小于除数。
运行时异常:若除数为0,抛出ArithmeticException。
ireturn
操作:从方法返回int
格式:ireturn
形式:ireturn = 172 (0xac)
操作数栈:
..., value → [empty]描述:当前方法返回类型为boolean、byte、char、short或int。value为int。若为同步方法,退出监视器。弹出value压入调用者栈。在压入前可能需转换:若返回类型为byte、char或short,分别如同执行i2b、i2c或i2s;若为boolean,取value & 1。
运行时异常:结构化锁定异常,同areturn。
ishl
操作:int左移
格式:ishl
形式:ishl = 120 (0x78)
操作数栈:
..., value1, value2 → ..., result描述:弹出value1(int)和value2(int),将value1左移s位,其中s为value2的低5位。结果压栈。相当于乘以2的s次幂(溢出时亦然)。移位距离始终在0~31。
ishr
操作:int算术右移
格式:ishr
形式:ishr = 122 (0x7a)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个int,将value1右移s位(符号扩展),s为value2低5位。结果压栈。相当于 floor(value1 / 2^s)。
istore
操作:将int存储到局部变量
格式:istore index
形式:istore = 54 (0x36)
操作数栈:
..., value → ...描述:index为局部变量索引,弹出栈顶int,存储到index。
注意:可与wide配合。
istore_<n>
操作:将int存储到局部变量
格式:istore_<n>
形式:
istore_0 = 59 (0x3b)
istore_1 = 60 (0x3c)
istore_2 = 61 (0x3d)
istore_3 = 62 (0x3e)操作数栈:
..., value → ...描述:<n>为索引,存储int。
isub
操作:int减法
格式:isub
形式:isub = 100 (0x64)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 - value2,取低32位。溢出不抛异常。
iushr
操作:int逻辑右移
格式:iushr
形式:iushr = 124 (0x7c)
操作数栈:
..., value1, value2 → ..., result描述:将value1右移s位(零扩展),s为value2低5位。结果压栈。
ixor
操作:int按位异或
格式:ixor
形式:ixor = 130 (0x82)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个int,按位异或后压栈。
jsr
操作:跳转子程序
格式:jsr branchbyte1 branchbyte2
形式:jsr = 168 (0xa8)
操作数栈:
... → ..., address描述:将紧随jsr的指令的地址(returnAddress类型)压栈,然后跳转到目标偏移。目标必须为方法内指令。
注意:jsr压栈地址,ret从局部变量取出。在Java SE 6之前用于实现finally。
jsr_w
操作:跳转子程序(宽偏移)
格式:jsr_w branchbyte1 branchbyte2 branchbyte3 branchbyte4
形式:jsr_w = 201 (0xc9)
操作数栈:
... → ..., address描述:类似jsr,但偏移为32位。
l2d
操作:将long转换为double
格式:l2d
形式:l2d = 138 (0x8a)
操作数栈:
..., value → ..., result描述:弹出long,使用向最近舍入转换为double。可能丢失精度(double只有53位有效数)。
l2f
操作:将long转换为float
格式:l2f
形式:l2f = 137 (0x89)
操作数栈:
..., value → ..., result描述:弹出long,向最近舍入转换为float,可能丢失精度(float只有24位有效数)。
l2i
操作:将long转换为int
格式:l2i
形式:l2i = 136 (0x88)
操作数栈:
..., value → ..., result描述:取long低32位作为int。
注意:窄化转换,可能丢失信息。
ladd
操作:long加法
格式:ladd
形式:ladd = 97 (0x61)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个long,计算和,取低64位。溢出不抛异常。
laload
操作:从数组加载long
格式:laload
形式:laload = 47 (0x2f)
操作数栈:
..., arrayref, index → ..., value描述:arrayref引用long数组,弹出索引,取出long值压栈。
运行时异常:同aaload。
land
操作:long按位与
格式:land
形式:land = 127 (0x7f)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个long,按位与压栈。
lastore
操作:存储到long数组
格式:lastore
形式:lastore = 80 (0x50)
操作数栈:
..., arrayref, index, value → ...描述:arrayref引用long数组,弹出index(int)和value(long),存储。
运行时异常:同aastore。
lcmp
操作:比较long
格式:lcmp
形式:lcmp = 148 (0x94)
操作数栈:
..., value1, value2 → ..., result描述:弹出两个long,有符号比较:大于压入1,等于0,小于-1。
lconst_<l>
操作:压入long常量
格式:lconst_<l>
形式:
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)操作数栈:
... → ..., <l>描述:压入0L或1L。
ldc
操作:从运行时常量池压入项
格式:ldc index
形式:ldc = 18 (0x12)
操作数栈:
... → ..., value描述:index为常量池索引,条目必须是可加载的(§5.1),且不是long/double或描述符为J/D的CONSTANT_Dynamic。根据条目类型压入int、float、String、Class、MethodType、MethodHandle或动态常量。
链接异常:解析时可能抛出相应异常。
ldc_w
操作:从运行时常量池压入项(宽索引)
格式:ldc_w indexbyte1 indexbyte2
形式:ldc_w = 19 (0x13)
操作数栈:
... → ..., value描述:类似ldc,但索引为16位。
ldc2_w
操作:从运行时常量池压入long或double(宽索引)
格式:ldc2_w indexbyte1 indexbyte2
形式:ldc2_w = 20 (0x14)
操作数栈:
... → ..., value描述:索引条目必须是long/double常量或描述符为J/D的CONSTANT_Dynamic,压入对应的long或double。
ldiv
操作:long除法
格式:ldiv
形式:ldiv = 109 (0x6d)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 / value2,向零舍入。特殊:被除数为long最小值且除数为-1,结果等于被除数(溢出不抛异常)。若除数为0,抛出ArithmeticException。
lload
操作:从局部变量加载long
格式:lload index
形式:lload = 22 (0x16)
操作数栈:
... → ..., value描述:index和index+1为索引,加载long值。
注意:可与wide配合。
lload_<n>
操作:从局部变量加载long
格式:lload_<n>
形式:
lload_0 = 30 (0x1e)
lload_1 = 31 (0x1f)
lload_2 = 32 (0x20)
lload_3 = 33 (0x21)操作数栈:
... → ..., value描述:<n>和<n>+1索引,加载long。
lmul
操作:long乘法
格式:lmul
形式:lmul = 105 (0x69)
操作数栈:
..., value1, value2 → ..., result描述:计算乘积,取低64位。溢出不抛异常。
lneg
操作:long取反
格式:lneg
形式:lneg = 117 (0x75)
操作数栈:
..., value → ..., result描述:计算-value,对最大负数取反仍为自身(溢出不抛异常)。
lookupswitch
操作:通过键匹配访问跳转表
格式:lookupswitch <0-3字节填充> default... npairs... match-offset pairs...
形式:lookupswitch = 171 (0xab)
操作数栈:
..., key → ...描述:变长指令。填充使默认偏移量4字节对齐。弹出int key,在匹配偏移对表中查找,若匹配则跳转到对应偏移,否则跳转到默认目标。匹配对必须按键升序排序。所有目标必须在方法内。
注意:排序是为了支持比线性搜索更快的查找。
lor
操作:long按位或
格式:lor
形式:lor = 129 (0x81)
操作数栈:
..., value1, value2 → ..., result描述:按位或压栈。
lrem
操作:long取余
格式:lrem
形式:lrem = 113 (0x71)
操作数栈:
..., value1, value2 → ..., result描述:类似irem,但操作long。若除数为0,抛出ArithmeticException。
lreturn
操作:从方法返回long
格式:lreturn
形式:lreturn = 173 (0xad)
操作数栈:
..., value → [empty]描述:返回long,同步处理。异常同areturn。
lshl
操作:long左移
格式:lshl
形式:lshl = 121 (0x79)
操作数栈:
..., value1, value2 → ..., result描述:value1为long,value2为int,左移s位(s为value2低6位),结果压栈。
lshr
操作:long算术右移
格式:lshr
形式:lshr = 123 (0x7b)
操作数栈:
..., value1, value2 → ..., result描述:符号扩展右移,s为value2低6位。
lstore
操作:将long存储到局部变量
格式:lstore index
形式:lstore = 55 (0x37)
操作数栈:
..., value → ...描述:弹出long,存储到index和index+1。
lstore_<n>
操作:将long存储到局部变量
格式:lstore_<n>
形式:
lstore_0 = 63 (0x3f)
lstore_1 = 64 (0x40)
lstore_2 = 65 (0x41)
lstore_3 = 66 (0x42)操作数栈:
..., value → ...描述:存储到<n>和<n>+1。
lsub
操作:long减法
格式:lsub
形式:lsub = 101 (0x65)
操作数栈:
..., value1, value2 → ..., result描述:计算value1 - value2,取低64位。溢出不抛异常。
lushr
操作:long逻辑右移
格式:lushr
形式:lushr = 125 (0x7d)
操作数栈:
..., value1, value2 → ..., result描述:零扩展右移,s为value2低6位。
lxor
操作:long按位异或
格式:lxor
形式:lxor = 131 (0x83)
操作数栈:
..., value1, value2 → ..., result描述:按位异或压栈。
monitorenter
操作:进入对象的监视器
格式:monitorenter
形式:monitorenter = 194 (0xc2)
操作数栈:
..., objectref → ...描述:objectref为reference。尝试获取对象关联的监视器所有权:若计数为0则进入并设计数为1;若当前线程已拥有则重入计数加1;否则阻塞直到计数为0。
运行时异常:若objectref为null,抛出NullPointerException。
注意:用于实现synchronized块,同步方法由ACC_SYNCHRONIZED隐式处理。
monitorexit
操作:退出对象的监视器
格式:monitorexit
形式:monitorexit = 195 (0xc3)
操作数栈:
..., objectref → ...描述:当前线程必须是监视器所有者。递减计数,若变为0则退出。
运行时异常:若objectref为null,抛出NullPointerException;若当前线程不是所有者,抛出IllegalMonitorStateException;若违反结构化锁定规则,也抛出该异常。
multianewarray
操作:创建多维数组
格式:multianewarray indexbyte1 indexbyte2 dimensions
形式:multianewarray = 197 (0xc5)
操作数栈:
..., count1, [count2, ...] → ..., arrayref描述:dimensions为无符号字节(≥1)。弹出dimensions个int计数,各表示对应维度的长度。解析数组类引用,其维度必须≥dimensions。分配多维数组,若某计数为0则后续维度不分配。组件初始化为默认值。压入引用。
链接异常:解析异常;若无权访问元素类型,抛出IllegalAccessError。
运行时异常:若任何计数<0,抛出NegativeArraySizeException。
注意:可通过newarray或anewarray创建一维数组以提高效率。
new
操作:创建新对象
格式:new indexbyte1 indexbyte2
形式:new = 187 (0xbb)
操作数栈:
... → ..., objectref描述:解析类引用,必须为类类型(非接口/抽象)。分配内存,实例变量初始化为默认值,压入引用。解析后初始化类(若未初始化)。
链接异常:解析异常;若解析为接口或抽象类,抛出InstantiationError。
运行时异常:初始化可能抛出Error。
注意:new未完成实例创建,需随后调用<init>。
newarray
操作:创建新数组
格式:newarray atype
形式:newarray = 188 (0xbc)
操作数栈:
..., count → ..., arrayref描述:count为int(元素个数)。atype为类型码(表6.5.newarray-A),如T_BOOLEAN=4、T_CHAR=5等。分配数组,组件初始化为默认值,压入引用。
运行时异常:若count<0,抛出NegativeArraySizeException。
nop
操作:无操作
格式:nop
形式:nop = 0 (0x0)
操作数栈:无变化
描述:不执行任何操作。
pop
操作:弹出栈顶值
格式:pop
形式:pop = 87 (0x57)
操作数栈:
..., value → ...描述:弹出栈顶值(类别1类型)。
pop2
操作:弹出栈顶一个或两个值
格式:pop2
形式:pop2 = 88 (0x58)
操作数栈:
- 形式1:
..., value2, value1 → ...(两个类别1) - 形式2:
..., value → ...(一个类别2)
描述:弹出栈顶一个类别2值或两个类别1值。
putfield
操作:设置对象中的字段
格式:putfield indexbyte1 indexbyte2
形式:putfield = 181 (0xb5)
操作数栈:
..., objectref, value → ...描述:解析字段引用。value类型必须与字段描述符兼容(若为boolean则取value & 1)。若字段为final,必须声明在当前类且指令位于实例初始化方法中。弹出objectref和value,设置字段。
链接异常:字段解析错误;若为静态字段抛出IncompatibleClassChangeError;若final不合法抛出IllegalAccessError。
运行时异常:objectref为null抛出NullPointerException。
putstatic
操作:设置类中的静态字段
格式:putstatic indexbyte1 indexbyte2
形式:putstatic = 179 (0xb3)
操作数栈:
..., value → ...描述:解析静态字段,初始化声明类。value类型必须兼容,若为boolean则&1。若为final,必须声明在当前类/接口且指令位于类/接口初始化方法中。设置字段。
链接异常:类似putfield,但针对静态字段,若为非静态抛出IncompatibleClassChangeError。
运行时异常:初始化可能抛出Error。
注意:接口字段只能在初始化时赋值一次。
ret
操作:从子程序返回
格式:ret index
形式:ret = 169 (0xa9)
操作数栈:无变化
描述:index为局部变量索引,该局部变量必须包含returnAddress。将地址写入PC,继续执行。
注意:与jsr配对使用。在Java SE 6之前用于finally。
return
操作:从方法返回void
格式:return
形式:return = 177 (0xb1)
操作数栈:
... → [empty]描述:当前方法返回void。同步方法退出监视器。丢弃栈上所有值,恢复调用者。
运行时异常:结构化锁定异常。
saload
操作:从数组加载short
格式:saload
形式:saload = 53 (0x35)
操作数栈:
..., arrayref, index → ..., value描述:arrayref引用short数组,取出组件值,符号扩展为int压栈。
运行时异常:同aaload。
sastore
操作:存储到short数组
格式:sastore
形式:sastore = 86 (0x56)
操作数栈:
..., arrayref, index, value → ...描述:arrayref引用short数组,value为int,截断为short存储。
运行时异常:同aastore。
sipush
操作:压入short
格式:sipush byte1 byte2
形式:sipush = 17 (0x11)
操作数栈:
... → ..., value描述:将两个字节组装为short,符号扩展为int压栈。
swap
操作:交换栈顶两个值
格式:swap
形式:swap = 95 (0x5f)
操作数栈:
..., value2, value1 → ..., value1, value2描述:交换栈顶两个值(必须都是类别1类型)。
注意:无类别2交换指令。
tableswitch
操作:通过索引访问跳转表并跳转
格式:tableswitch <0-3字节填充> default... low... high... jump offsets...
形式:tableswitch = 170 (0xaa)
操作数栈:
..., index → ...描述:变长指令,填充使偏移量4字节对齐。弹出int index,若index < low或index > high则跳到默认目标;否则从跳转表中取偏移量(位置index - low)跳转。所有目标在方法内。
wide
操作:扩展局部变量索引或增量范围
格式1:
wide
<opcode>
indexbyte1
indexbyte2其中<opcode>为iload、fload、aload、lload、dload、istore、fstore、astore、lstore、dstore或ret。
格式2:
wide
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2形式:wide = 196 (0xc4)
操作数栈:与被修改指令相同
描述:wide修改后跟指令的行为,使用16位索引(而不是8位)和16位增量(仅对iinc)。被修改的指令不得直接执行。