goto
是 Java 中的关键字, 但还处于保留状态, 在理论的开发中并不能应用. 本文列举了 Java 中的关键字以及引入工夫, 同时探讨了和 goto
成果相似的 break label
的语法以及应用的 demo. 最初从将 demo 进行了反编译并逐条剖析了 Java 字节码的执行, 得出的论断是 break label
底层比较简单就是一行 goto xx
的字节码指令. 在剖析字节码的过程中重温了一下 Java 基于栈实现的执行引擎运行.
原文地址:Java 中有 goto 吗?
欢送拜访我的博客: http://blog.duhbb.com/
Java 关键字
下表中列举了 Java 中的关键字, 这些关键字都不能够作为标识符. const
和 go
是保留关键字, 尽管没有正式应用, 然而你也不能把它们作为标识符. true
, false
和 null
尽管看上去像关键字, 然而它们实际上是 literals, 它们也不能作为标识符应用.
abstract | continue | for | new | switch |
assert*** | default | goto* | package | synchronized |
boolean | do | if | private | this |
break | double | implements | protected | throw |
byte | else | import | public | throws |
case | enum**** | instanceof | return | transient |
catch | extends | int | short | try |
char | final | interface | static | void |
class | finally | long | strictfp** | volatile |
const* | float | native | super | while |
备注:
*
: 未应用**
: 1.2 中引入***
:1.4 中引入****
:5.0 中引入
以上来自:Java Language Keywords
可见 Java 中的确有 goto
, 然而是保留的关键字, 并不能理论应用.So, 咱们不能 goto anywhere
.
break label 用法
尽管 Java 中没有 C 语言中 goto
的那种用法, 然而有一个 ” 相似 ” 的.
语法
语法格局: break label
, label 你能够本人定义, 只有不抵触就行.
break
语句能够终止带标签的语句的执行; 它并不会将控制流转移到标签上, 而是将控制流立刻转移到了带标签语句的下一条语句中.
例子
first:
for(int i = 0; i < 10; i++) {
second:
for(int j = 0; j < 5; j ++) {break xxx;}
}
third:
for(int a = 0; a < 10; a++) {}
xxx
只能是first
或者second
, 而不能是third
, 也就是只能 break 包裹break
的语句;break third
会报编译谬误.break first
会跳出最外层的 for 循环, 而break second
则会跳出内层的 for 循环, 外层的 for 循环持续.
查看字节码
源代码:Main.java
public class Main {public static void main(String[] args) {
first:
for (int i = 0; i < 10; i++) {
second:
for (int j = 0; j < 5; j++) {System.out.println("i =" + i + ", j =" + j);
break first;
}
}
third:
for (int a = 0; a < 10; a++) {System.out.println(a);
}
}
}
javap -v Main.class
反编译后的字节:
duhbb@debian:/mnt/data/IdeaProjects/test/target/classes$ javap -v Main.class
Classfile /mnt/data/IdeaProjects/test/target/classes/Main.class
Last modified 2022-6-8; size 913 bytes
MD5 checksum f56881b622c0cfceb531278564352491
Compiled from "Main.java"
public class Main
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #13.#32 // java/lang/Object."<init>":()V
#2 = Fieldref #33.#34 // java/lang/System.out:Ljava/io/PrintStream;
#3 = Class #35 // java/lang/StringBuilder
#4 = Methodref #3.#32 // java/lang/StringBuilder."<init>":()V
#5 = String #36 // i =
#6 = Methodref #3.#37 // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#7 = Methodref #3.#38 // java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
#8 = String #39 // , j =
#9 = Methodref #3.#40 // java/lang/StringBuilder.toString:()Ljava/lang/String;
#10 = Methodref #41.#42 // java/io/PrintStream.println:(Ljava/lang/String;)V
#11 = Methodref #41.#43 // java/io/PrintStream.println:(I)V
#12 = Class #44 // Main
#13 = Class #45 // java/lang/Object
#14 = Utf8 <init>
#15 = Utf8 ()V
#16 = Utf8 Code
#17 = Utf8 LineNumberTable
#18 = Utf8 LocalVariableTable
#19 = Utf8 this
#20 = Utf8 LMain;
#21 = Utf8 main
#22 = Utf8 ([Ljava/lang/String;)V
#23 = Utf8 j
#24 = Utf8 I
#25 = Utf8 i
#26 = Utf8 a
#27 = Utf8 args
#28 = Utf8 [Ljava/lang/String;
#29 = Utf8 StackMapTable
#30 = Utf8 SourceFile
#31 = Utf8 Main.java
#32 = NameAndType #14:#15 // "<init>":()V
#33 = Class #46 // java/lang/System
#34 = NameAndType #47:#48 // out:Ljava/io/PrintStream;
#35 = Utf8 java/lang/StringBuilder
#36 = Utf8 i =
#37 = NameAndType #49:#50 // append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
#38 = NameAndType #49:#51 // append:(I)Ljava/lang/StringBuilder;
#39 = Utf8 , j =
#40 = NameAndType #52:#53 // toString:()Ljava/lang/String;
#41 = Class #54 // java/io/PrintStream
#42 = NameAndType #55:#56 // println:(Ljava/lang/String;)V
#43 = NameAndType #55:#57 // println:(I)V
#44 = Utf8 Main
#45 = Utf8 java/lang/Object
#46 = Utf8 java/lang/System
#47 = Utf8 out
#48 = Utf8 Ljava/io/PrintStream;
#49 = Utf8 append
#50 = Utf8 (Ljava/lang/String;)Ljava/lang/StringBuilder;
#51 = Utf8 (I)Ljava/lang/StringBuilder;
#52 = Utf8 toString
#53 = Utf8 ()Ljava/lang/String;
#54 = Utf8 java/io/PrintStream
#55 = Utf8 println
#56 = Utf8 (Ljava/lang/String;)V
#57 = Utf8 (I)V
{public Main();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LMain;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=3, locals=3, args_size=1
0: iconst_0 // 将常数 0 压入操作数栈
1: istore_1 // 将操作数出栈, 并给到本地变量表的第 1 地位的变量, 也就是 i
2: iload_1 // 就是变量表中第 1 个地位的 i 压栈到操作数栈顶
3: bipush 10 // 把常量 10 压入到操作数栈中
5: if_icmpge 58 // 进行比拟, 如果为 false 则跳到 58 行 (我猜的)
8: iconst_0 // 将常数 0 压入操作数栈
9: istore_2 // 将其弹给并给到本地变量表的第 1 地位的变量, 也就是 j
10: iload_2 // 就是变量表中第 2 个地位的 i 压栈到操作数栈顶
11: iconst_5 // 把常量 5 压入到操作数栈中
12: if_icmpge 52 // 进行一通比拟, 如果为 false 则跳到 52 行执行
15: getstatic #2 // 获取类的动态字段 Field java/lang/System.out:Ljava/io/PrintStream;
18: new #3 // 创立一个对象, 对象是通过字节索引在常量池中定位的 class java/lang/StringBuilder
21: dup // 复制在栈顶的值
22: invokespecial #4 // 调用 StringBuilder 的办法进行初始化 Method java/lang/StringBuilder."<init>":()V
25: ldc #5 // 字符串入栈 String i =
27: invokevirtual #6 // 调用 StringBuilder 的 append 办法 Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
30: iload_1 // 就是变量表中第 1 个地位的 i 压栈到操作数栈顶 这里就是 i 了, 因为筹备把 i 拼接到前面去
31: invokevirtual #7 // 调用 StringBuilder 的 append Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
34: ldc #8 // 字符串入栈 String , j =
36: invokevirtual #6 // 调用 StringBuilder 的 append 办法 Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
39: iload_2 // 就是变量表中第 2 个地位的 j 压栈到操作数栈顶 这里就是 j 了, 因为筹备把 j 拼接到前面去
40: invokevirtual #7 // 调用 StringBuilder 的 append 办法 Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
43: invokevirtual #9 // 调用 StringBuilder 的 toString 办法 Method java/lang/StringBuilder.toString:()Ljava/lang/String;
46: invokevirtual #10 // 调用 PrintStream 的 println 办法 Method java/io/PrintStream.println:(Ljava/lang/String;)V
49: goto 58 // break first 毫无征兆的跳到了 58 行
52: iinc 1, 1
55: goto 2
58: iconst_0 // 开始了 third 局部的循环
59: istore_1
60: iload_1
61: bipush 10
63: if_icmpge 79
66: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
69: iload_1
70: invokevirtual #11 // Method java/io/PrintStream.println:(I)V
73: iinc 1, 1
76: goto 60
79: return
LineNumberTable:
line 8: 0
line 10: 8
line 11: 15
line 12: 49
line 8: 52
line 17: 58
line 18: 66
line 17: 73
line 20: 79
LocalVariableTable:
Start Length Slot Name Signature
10 42 2 j I
2 56 1 i I
60 19 1 a I
0 80 0 args [Ljava/lang/String;
StackMapTable: number_of_entries = 6
frame_type = 252 /* append */
offset_delta = 2
locals = [int]
frame_type = 252 /* append */
offset_delta = 7
locals = [int]
frame_type = 250 /* chop */
offset_delta = 41
frame_type = 250 /* chop */
offset_delta = 5
frame_type = 252 /* append */
offset_delta = 1
locals = [int]
frame_type = 250 /* chop */
offset_delta = 18
}
SourceFile: "Main.java"
常量入栈指令有 iconst
, bipush
, sipush
, ldc
, ldc2_w
别离对应不同的应用场景, 以下两个表简略总结了应用场景:
- 八大根本类型场景表
- 指令场景表
下面的两张图片来自于: Java 逆向根底之常量入栈指令
为啥要这么麻烦, 搞出这么多不通的入栈指令呢? 连 -1~5
这样的都要搞进去?
- bipush 8 就是把 8 压到操作数栈中.
- istore_1 就是操作数栈出栈, 存到本地变量表的第 1 地位;
- iload_1, 就是变量表中第一个地位的 i 压栈到操作数栈顶
- iinc 1 by 1, 就是变量表中第一个地位的
- istore_1, 又把栈顶的 8 存回了变量表中的 i
- dup 对于 dup 指令的作用, 在《深刻了解 Java 虚拟机》这本书中是这么形容的. 这是一个操作数栈治理指令, 负责复制栈顶 (留神, 这个栈指的是操作数栈) 一个或者两个数值并将复制值或双份的复制值从新压人栈顶.
简略了解就是给操作数栈栈顶的元素弄了一个备份.
那么为什么要进行备份呢?
一开始是 new 指令在堆上调配了内存并向操作数栈压入了指向这段内存的援用, 之后 dup 指令又备份了一份, 那么操作数栈顶就有两个, 再后是调用invokespecial #18
指令进行初始化, 此时会耗费一个援用作为传给结构器的this
参数, 那么还剩下一个援用, 会被 astore_1 指令存储到局部变量表中.dup 来自: Java 字节码 new 之后为什么会有 dup - invokespecial 的参数哪儿来的?
- ldc: 则是从常量池中将常量
Java 字节吗概述
Java 虚拟机采纳基于栈的架构, 其指令由操作码和操作数组成.
操作码: 一个字节长度 (0~255), 意味着指令集的操作码个数不能操作 256 条.
操作数: 一条指令能够有零或者多个操作数, 且操作数能够是 1 个或者多个字节. 编译后的代码没有采纳操作数长度对齐形式, 比方 16 位无符号整数需应用两个字节贮存 (假如为 byte1 和 byte2), 那么实在值是 (byte1 << 8) | byte2.
放弃操作数对齐操作数对齐计划:
劣势: 能够省略很多填充和距离符号, 从而缩小数据量, 具备更高的传输效率;Java 起初就是为了面向网络, 智能家具而设计的, 故更加重视传输效率.
劣势: 运行时从字节码里构建出具体数据结构, 须要破费局部 CPU 工夫, 从而导致解释执行字节码会损失局部性能.
指令介绍
大多数指令蕴含了其操作所对应的数据类型信息, 比方 iload, 示意从局部变量表中加载 int 型的数据到操作数栈; 而 fload 示意加载 float 型数据到操作数栈. 因为操作码长度只有 1Byte, 因而 Java 虚拟机的指令集对于特定操作只提供无限的类型相干指令, 并非为每一种数据类型都有相应的操作指令. 必要时, 有些指令可用于将不反对的类型转换为可被反对的类型.
对于 byte,short,char,boolean 类型, 往往没有独自的操作码, 通过编译器在编译期或者运行期将其扩大. 对于 byte,short 采纳带符号扩大,chart,boolean 采纳零位扩大. 相应的数组也是采纳相似的扩大形式转换为 int 类型的字节码来解决. 上面分门别类来介绍 Java 虚拟机指令, 都以 int 类型的数据操作为例.
栈是指操作数栈.
这两个局部来自:Jvm 系列 3—字节码指令
字节码指令介绍:
指令 | 含意 | |||
---|---|---|---|---|
aaload | load onto the stack a reference from an array | |||
aastore | store a reference in an array | |||
aconst_null | push a null reference onto the stack | |||
aload | load a reference onto the stack from a local variable #index | |||
aload_0 | load a reference onto the stack from local variable 0 | |||
aload_1 | load a reference onto the stack from local variable 1 | |||
aload_2 | load a reference onto the stack from local variable 2 | |||
aload_3 | load a reference onto the stack from local variable 3 | |||
anewarray | create a new array of references of length count and component type identified by the class reference index (indexbyte1 << 8 \ | indexbyte2) in the constant pool | ||
areturn | return a reference from a method | |||
arraylength | get the length of an array | |||
astore | store a reference into a local variable #index | |||
astore_0 | store a reference into local variable 0 | |||
astore_1 | store a reference into local variable 1 | |||
astore_2 | store a reference into local variable 2 | |||
astore_3 | store a reference into local variable 3 | |||
athrow | throws an error or exception (notice that the rest of the stack is cleared, leaving only a reference to the Throwable) | |||
baload | load a byte or Boolean value from an array | |||
bastore | store a byte or Boolean value into an array | |||
bipush | push a byte onto the stack as an integer value | |||
breakpoint | reserved for breakpoints in Java debuggers; should not appear in any class file | |||
caload | load a char from an array | |||
castore | store a char into an array | |||
checkcast | checks whether an objectref is of a certain type, the class reference of which is in the constant pool at index (indexbyte1 << 8 \ | indexbyte2) | ||
d2f | convert a double to a float | |||
d2i | convert a double to an int | |||
d2l | convert a double to a long | |||
dadd | add two doubles | |||
daload | load a double from an array | |||
dastore | store a double into an array | |||
dcmpg | compare two doubles, 1 on NaN | |||
dcmpl | compare two doubles, -1 on NaN | |||
dconst_0 | push the constant 0.0 (a double) onto the stack | |||
dconst_1 | push the constant 1.0 (a double) onto the stack | |||
ddiv | divide two doubles | |||
dload | load a double value from a local variable #index | |||
dload_0 | load a double from local variable 0 | |||
dload_1 | load a double from local variable 1 | |||
dload_2 | load a double from local variable 2 | |||
dload_3 | load a double from local variable 3 | |||
dmul | multiply two doubles | |||
dneg | negate a double | |||
drem | get the remainder from a division between two doubles | |||
dreturn | return a double from a method | |||
dstore | store a double value into a local variable #index | |||
dstore_0 | store a double into local variable 0 | |||
dstore_1 | store a double into local variable 1 | |||
dstore_2 | store a double into local variable 2 | |||
dstore_3 | store a double into local variable 3 | |||
dsub | subtract a double from another | |||
dup | duplicate the value on top of the stack | |||
dup_x1 | insert a copy of the top value into the stack two values from the top. value1 and value2 must not be of the type double or long. | |||
dup_x2 | insert a copy of the top value into the stack two (if value2 is double or long it takes up the entry of value3, too) or three values (if value2 is neither double nor long) from the top | |||
dup2 | duplicate top two stack words (two values, if value1 is not double nor long; a single value, if value1 is double or long) | |||
dup2_x1 | duplicate two words and insert beneath third word (see explanation above) | |||
dup2_x2 | duplicate two words and insert beneath fourth word | |||
f2d | convert a float to a double | |||
f2i | convert a float to an int | |||
f2l | convert a float to a long | |||
fadd | add two floats | |||
faload | load a float from an array | |||
fastore | store a float in an array | |||
fcmpg | compare two floats, 1 on NaN | |||
fcmpl | compare two floats, -1 on NaN | |||
fconst_0 | push 0.0f on the stack | |||
fconst_1 | push 1.0f on the stack | |||
fconst_2 | push 2.0f on the stack | |||
fdiv | divide two floats | |||
fload | load a float value from a local variable #index | |||
fload_0 | load a float value from local variable 0 | |||
fload_1 | load a float value from local variable 1 | |||
fload_2 | load a float value from local variable 2 | |||
fload_3 | load a float value from local variable 3 | |||
fmul | multiply two floats | |||
fneg | negate a float | |||
frem | get the remainder from a division between two floats | |||
freturn | return a float | |||
fstore | store a float value into a local variable #index | |||
fstore_0 | store a float value into local variable 0 | |||
fstore_1 | store a float value into local variable 1 | |||
fstore_2 | store a float value into local variable 2 | |||
fstore_3 | store a float value into local variable 3 | |||
fsub | subtract two floats | |||
getfield | get a field value of an object objectref, where the field is identified by field reference in the constant pool index (indexbyte1 << 8 \ | indexbyte2) | ||
getstatic | get a static field value of a class, where the field is identified by field reference in the constant pool index (indexbyte1 << 8 \ | indexbyte2) | ||
goto | goes to another instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
goto_w | goes to another instruction at branchoffset (signed int constructed from unsigned bytes branchbyte1 << 24 \ | branchbyte2 << 16 \ | branchbyte3 << 8 \ | branchbyte4) |
i2b | convert an int into a byte | |||
i2c | convert an int into a character | |||
i2d | convert an int into a double | |||
i2f | convert an int into a float | |||
i2l | convert an int into a long | |||
i2s | convert an int into a short | |||
iadd | add two ints | |||
iaload | load an int from an array | |||
iand | perform a bitwise AND on two integers | |||
iastore | store an int into an array | |||
iconst_m1 | load the int value −1 onto the stack | |||
iconst_0 | load the int value 0 onto the stack | |||
iconst_1 | load the int value 1 onto the stack | |||
iconst_2 | load the int value 2 onto the stack | |||
iconst_3 | load the int value 3 onto the stack | |||
iconst_4 | load the int value 4 onto the stack | |||
iconst_5 | load the int value 5 onto the stack | |||
idiv | divide two integers | |||
if_acmpeq | if references are equal, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
if_acmpne | if references are not equal, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
if_icmpeq | if ints are equal, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
if_icmpge | if value1 is greater than or equal to value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
if_icmpgt | if value1 is greater than value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
if_icmple | if value1 is less than or equal to value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
if_icmplt | if value1 is less than value2, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
if_icmpne | if ints are not equal, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
ifeq | if value is 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
ifge | if value is greater than or equal to 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
ifgt | if value is greater than 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
ifle | if value is less than or equal to 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
iflt | if value is less than 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
ifne | if value is not 0, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
ifnonnull | if value is not null, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
ifnull | if value is null, branch to instruction at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) | ||
iinc | increment local variable #index by signed byte const | |||
iload | load an int value from a local variable #index | |||
iload_0 | load an int value from local variable 0 | |||
iload_1 | load an int value from local variable 1 | |||
iload_2 | load an int value from local variable 2 | |||
iload_3 | load an int value from local variable 3 | |||
impdep1 | reserved for implementation-dependent operations within debuggers; should not appear in any class file | |||
impdep2 | reserved for implementation-dependent operations within debuggers; should not appear in any class file | |||
imul | multiply two integers | |||
ineg | negate int | |||
instanceof | determines if an object objectref is of a given type, identified by class reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
invokedynamic | invokes a dynamic method and puts the result on the stack (might be void); the method is identified by method reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
invokeinterface | invokes an interface method on object objectref and puts the result on the stack (might be void); the interface method is identified by method reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
invokespecial | invoke instance method on object objectref and puts the result on the stack (might be void); the method is identified by method reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
invokestatic | invoke a static method and puts the result on the stack (might be void); the method is identified by method reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
invokevirtual | invoke virtual method on object objectref and puts the result on the stack (might be void); the method is identified by method reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
ior | bitwise int OR | |||
irem | logical int remainder | |||
ireturn | return an integer from a method | |||
ishl | int shift left | |||
ishr | int arithmetic shift right | |||
istore | store int value into variable #index | |||
istore_0 | store int value into variable 0 | |||
istore_1 | store int value into variable 1 | |||
istore_2 | store int value into variable 2 | |||
istore_3 | store int value into variable 3 | |||
isub | int subtract | |||
iushr | int logical shift right | |||
ixor | int xor | |||
jsr† | jump to subroutine at branchoffset (signed short constructed from unsigned bytes branchbyte1 << 8 \ | branchbyte2) and place the return address on the stack | ||
jsr_w† | jump to subroutine at branchoffset (signed int constructed from unsigned bytes branchbyte1 << 24 \ | branchbyte2 << 16 \ | branchbyte3 << 8 \ | branchbyte4) and place the return address on the stack |
l2d | convert a long to a double | |||
l2f | convert a long to a float | |||
l2i | convert a long to a int | |||
ladd | add two longs | |||
laload | load a long from an array | |||
land | bitwise AND of two longs | |||
lastore | store a long to an array | |||
lcmp | push 0 if the two longs are the same, 1 if value1 is greater than value2, -1 otherwise | |||
lconst_0 | push 0L (the number zero with type long) onto the stack | |||
lconst_1 | push 1L (the number one with type long) onto the stack | |||
ldc | push a constant #index from a constant pool (String, int, float, Class, java.lang.invoke.MethodType, java.lang.invoke.MethodHandle, or a dynamically-computed constant) onto the stack | |||
ldc_w | push a constant #index from a constant pool (String, int, float, Class, java.lang.invoke.MethodType, java.lang.invoke.MethodHandle, or a dynamically-computed constant) onto the stack (wide index is constructed as indexbyte1 << 8 \ | indexbyte2) | ||
ldc2_w | push a constant #index from a constant pool (double, long, or a dynamically-computed constant) onto the stack (wide index is constructed as indexbyte1 << 8 \ | indexbyte2) | ||
ldiv | divide two longs | |||
lload | load a long value from a local variable #index | |||
lload_0 | load a long value from a local variable 0 | |||
lload_1 | load a long value from a local variable 1 | |||
lload_2 | load a long value from a local variable 2 | |||
lload_3 | load a long value from a local variable 3 | |||
lmul | multiply two longs | |||
lneg | negate a long | |||
lookupswitch | a target address is looked up from a table using a key and execution continues from the instruction at that address | |||
lor | bitwise OR of two longs | |||
lrem | remainder of division of two longs | |||
lreturn | return a long value | |||
lshl | bitwise shift left of a long value1 by int value2 positions | |||
lshr | bitwise shift right of a long value1 by int value2 positions | |||
lstore | store a long value in a local variable #index | |||
lstore_0 | store a long value in a local variable 0 | |||
lstore_1 | store a long value in a local variable 1 | |||
lstore_2 | store a long value in a local variable 2 | |||
lstore_3 | store a long value in a local variable 3 | |||
lsub | subtract two longs | |||
lushr | bitwise shift right of a long value1 by int value2 positions, unsigned | |||
lxor | bitwise XOR of two longs | |||
monitorenter | enter monitor for object (“grab the lock” – start of synchronized() section) | |||
monitorexit | exit monitor for object (“release the lock” – end of synchronized() section) | |||
multianewarray | create a new array of dimensions dimensions of type identified by class reference in constant pool index (indexbyte1 << 8 \ | indexbyte2); the sizes of each dimension is identified by count1, [count2, etc.] | ||
new | create new object of type identified by class reference in constant pool index (indexbyte1 << 8 \ | indexbyte2) | ||
newarray | create new array with count elements of primitive type identified by atype | |||
nop | perform no operation | |||
pop | discard the top value on the stack | |||
pop2 | discard the top two values on the stack (or one value, if it is a double or long) | |||
putfield | set field to value in an object objectref, where the field is identified by a field reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
putstatic | set static field to value in a class, where the field is identified by a field reference index in constant pool (indexbyte1 << 8 \ | indexbyte2) | ||
ret† | continue execution from address taken from a local variable #index (the asymmetry with jsr is intentional) | |||
return | return void from method | |||
saload | load short from array | |||
sastore | store short to array | |||
sipush | push a short onto the stack as an integer value | |||
swap | swaps two top words on the stack (note that value1 and value2 must not be double or long) | |||
tableswitch | continue execution from an address in the table at offset index | |||
wide | execute opcode, where opcode is either iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, or ret, but assume the index is 16 bit; or execute iinc, where the index is 16 bits and the constant to increment by is a signed 16 bit short | |||
(no name) | these values are currently unassigned for opcodes and are reserved for future use |
这个是我从 List of Java bytecode instructions 这里扣下来的.
待实现
字节码指令翻译.
原文地址:Java 中有 goto 吗?
欢送拜访我的博客: http://blog.duhbb.com/