概览
从 Instruction 的角度来说,与 math 相关的 opcode 有 52 个,内容如下:
opcode | mnemonic symbol | opcode | mnemonic symbol | opcode | mnemonic symbol | opcode | mnemonic symbol |
---|---|---|---|---|---|---|---|
96 | iadd | 109 | ldiv | 122 | ishr | 135 | i2d |
97 | ladd | 110 | fdiv | 123 | lshr | 136 | l2i |
98 | fadd | 111 | ddiv | 124 | iushr | 137 | l2f |
99 | dadd | 112 | irem | 125 | lushr | 138 | l2d |
100 | isub | 113 | lrem | 126 | iand | 139 | f2i |
101 | lsub | 114 | frem | 127 | land | 140 | f2l |
102 | fsub | 115 | drem | 128 | ior | 141 | f2d |
103 | dsub | 116 | ineg | 129 | lor | 142 | d2i |
104 | imul | 117 | lneg | 130 | ixor | 143 | d2l |
105 | lmul | 118 | fneg | 131 | lxor | 144 | d2f |
106 | fmul | 119 | dneg | 132 | iinc | 145 | i2b |
107 | dmul | 120 | ishl | 133 | i2l | 146 | i2c |
108 | idiv | 121 | lshl | 134 | i2f | 147 | i2s |
从 ASM 的角度来说,这些 opcode 与 MethodVisitor.visitXxxInsn()
方法对应关系如下:
MethodVisitor.visitInsn()
:iadd
,isub
,imul
,idiv
,irem
,ineg
ladd
,lsub
,lmul
,ldiv
,lrem
,lneg
fadd
,fsub
,fmul
,fdiv
,frem
,fneg
dadd
,dsub
,dmul
,ddiv
,drem
,dneg
ishl
,ishr
,iushr
,iand
,ior
,ixor
(int 类型的位操作)lshl
,lshr
,lushr
,land
,lor
,lxor
(long 类型的位操作)i2l
,i2f
,i2d
,i2b
,i2c
,i2s
l2i
,l2f
,l2d
f2i
,f2l
,f2d
d2i
,d2l
,d2f
MethodVisitor.visitIincInsn()
:iinc
Arithmetic
int: add/sub/mul/div/rem
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
int c = a + b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: istore_3
8: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitInsn(IADD);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_2 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: iload_2 // {this, int, int} | {int, int}
0006: iadd // {this, int, int} | {int}
0007: istore_3 // {this, int, int, int} | {}
0008: return // {} | {}
从 JVM 规范的角度来看,iadd
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
long: add/sub/mul/div/rem
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
long a = 1;
long b = 2;
long c = a + b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: lconst_1
1: lstore_1
2: ldc2_w #2 // long 2l
5: lstore_3
6: lload_1
7: lload_3
8: ladd
9: lstore 5
11: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(LCONST_1);
methodVisitor.visitVarInsn(LSTORE, 1);
methodVisitor.visitLdcInsn(new Long(2L));
methodVisitor.visitVarInsn(LSTORE, 3);
methodVisitor.visitVarInsn(LLOAD, 1);
methodVisitor.visitVarInsn(LLOAD, 3);
methodVisitor.visitInsn(LADD);
methodVisitor.visitVarInsn(LSTORE, 5);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(4, 7);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: lconst_1 // {this} | {long, top}
0001: lstore_1 // {this, long, top} | {}
0002: ldc2_w #2 // {this, long, top} | {long, top}
0005: lstore_3 // {this, long, top, long, top} | {}
0006: lload_1 // {this, long, top, long, top} | {long, top}
0007: lload_3 // {this, long, top, long, top} | {long, top, long, top}
0008: ladd // {this, long, top, long, top} | {long, top}
0009: lstore 5 // {this, long, top, long, top, long, top} | {}
0011: return // {} | {}
从 JVM 规范的角度来看,ladd
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type long
. The values are popped from the operand stack. The long result
is value1 + value2
. The result
is pushed onto the operand stack.
int: ineg
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = -a;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iload_1
3: ineg
4: istore_2
5: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitInsn(INEG);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 3);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iload_1 // {this, int} | {int}
0003: ineg // {this, int} | {int}
0004: istore_2 // {this, int, int} | {}
0005: return // {} | {}
从 JVM 规范的角度来看,ineg
指令对应的 Operand Stack 的变化如下:
..., value →
..., result
The value
must be of type int
. It is popped from the operand stack. The int result
is the arithmetic negation of value
, -value
. The result
is pushed onto the operand stack.
long: lneg
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
long a = 1;
long b = -a;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: lconst_1
1: lstore_1
2: lload_1
3: lneg
4: lstore_3
5: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(LCONST_1);
methodVisitor.visitVarInsn(LSTORE, 1);
methodVisitor.visitVarInsn(LLOAD, 1);
methodVisitor.visitInsn(LNEG);
methodVisitor.visitVarInsn(LSTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 5);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: lconst_1 // {this} | {long, top}
0001: lstore_1 // {this, long, top} | {}
0002: lload_1 // {this, long, top} | {long, top}
0003: lneg // {this, long, top} | {long, top}
0004: lstore_3 // {this, long, top, long, top} | {}
0005: return // {} | {}
从 JVM 规范的角度来看,lneg
指令对应的 Operand Stack 的变化如下:
..., value →
..., result
The value
must be of type long
. It is popped from the operand stack. The long result
is the arithmetic negation of value
, -value
. The result
is pushed onto the operand stack.
int: iinc
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int i = 0;
i++;
i += 10;
i -= 5;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_0
1: istore_1
2: iinc 1, 1
5: iinc 1, 10
8: iinc 1, -5
11: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitIincInsn(1, 1);
methodVisitor.visitIincInsn(1, 10);
methodVisitor.visitIincInsn(1, -5);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 2);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_0 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iinc 1 1 // {this, int} | {}
0005: iinc 1 10 // {this, int} | {}
0008: iinc 1 -5 // {this, int} | {}
0011: return // {} | {}
从 JVM 规范的角度来看,iinc
指令对应的 Operand Stack 的变化如下:
No change
Bit Shift
shift left
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
int c = a << b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: ishl
7: istore_3
8: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitInsn(ISHL);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_2 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: iload_2 // {this, int, int} | {int, int}
0006: ishl // {this, int, int} | {int}
0007: istore_3 // {this, int, int, int} | {}
0008: return // {} | {}
从 JVM 规范的角度来看,ishl
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type int
. The values are popped from the operand stack. An int result
is calculated by shifting value1
left by s
bit positions, where s
is the value of the low 5 bits of value2
. The result
is pushed onto the operand stack.
arithmetic shift right
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
int c = a >> b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: ishr
7: istore_3
8: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitInsn(ISHR);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_2 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: iload_2 // {this, int, int} | {int, int}
0006: ishr // {this, int, int} | {int}
0007: istore_3 // {this, int, int, int} | {}
0008: return // {} | {}
从 JVM 规范的角度来看,ishr
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type int
. The values are popped from the operand stack. An int result
is calculated by shifting value1
right by s
bit positions, with sign extension, where s
is the value of the low 5 bits of value2
. The result
is pushed onto the operand stack.
logical shift right
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
int c = a >>> b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iushr
7: istore_3
8: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitInsn(IUSHR);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_2 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: iload_2 // {this, int, int} | {int, int}
0006: iushr // {this, int, int} | {int}
0007: istore_3 // {this, int, int, int} | {}
0008: return // {} | {}
从 JVM 规范的角度来看,iushr
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type int
. The values are popped from the operand stack. An int result
is calculated by shifting value1
right by s
bit positions, with zero extension, where s
is the value of the low 5 bits of value2
. The result
is pushed onto the operand stack.
Bit Logic
and
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
int c = a & b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iand
7: istore_3
8: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitInsn(IAND);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_2 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: iload_2 // {this, int, int} | {int, int}
0006: iand // {this, int, int} | {int}
0007: istore_3 // {this, int, int, int} | {}
0008: return // {} | {}
从 JVM 规范的角度来看,iand
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type int
. They are popped from the operand stack. An int result
is calculated by taking the bitwise AND (conjunction) of value1
and value2
. The result
is pushed onto the operand stack.
or
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
int c = a | b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: ior
7: istore_3
8: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitInsn(IOR);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_2 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: iload_2 // {this, int, int} | {int, int}
0006: ior // {this, int, int} | {int}
0007: istore_3 // {this, int, int, int} | {}
0008: return // {} | {}
从 JVM 规范的角度来看,ior
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type int
. They are popped from the operand stack. An int result
is calculated by taking the bitwise inclusive OR of value1
and value2
. The result
is pushed onto the operand stack.
xor
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 1;
int b = 2;
int c = a ^ b;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: ixor
7: istore_3
8: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitVarInsn(ILOAD, 2);
methodVisitor.visitInsn(IXOR);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_1 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iconst_2 // {this, int} | {int}
0003: istore_2 // {this, int, int} | {}
0004: iload_1 // {this, int, int} | {int}
0005: iload_2 // {this, int, int} | {int, int}
0006: ixor // {this, int, int} | {int}
0007: istore_3 // {this, int, int, int} | {}
0008: return // {} | {}
从 JVM 规范的角度来看,ixor
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type int
. They are popped from the operand stack. An int result
is calculated by taking the bitwise exclusive OR of value1
and value2
. The result
is pushed onto the operand stack.
not
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int a = 0;
int b = ~a;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iconst_m1
4: ixor
5: istore_2
6: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitInsn(ICONST_M1);
methodVisitor.visitInsn(IXOR);
methodVisitor.visitVarInsn(ISTORE, 2);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 3);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_0 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iload_1 // {this, int} | {int}
0003: iconst_m1 // {this, int} | {int, int}
0004: ixor // {this, int} | {int}
0005: istore_2 // {this, int, int} | {}
0006: return // {} | {}
从 JVM 规范的角度来看,ixor
指令对应的 Operand Stack 的变化如下:
..., value1, value2 →
..., result
Both value1
and value2
must be of type int
. They are popped from the operand stack. An int result
is calculated by taking the bitwise exclusive OR of value1
and value2
. The result
is pushed onto the operand stack.
Type Conversion
int to long
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
int intValue = 0;
long longValue = intValue;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: iconst_0
1: istore_1
2: iload_1
3: i2l
4: lstore_2
5: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitVarInsn(ILOAD, 1);
methodVisitor.visitInsn(I2L);
methodVisitor.visitVarInsn(LSTORE, 2);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: iconst_0 // {this} | {int}
0001: istore_1 // {this, int} | {}
0002: iload_1 // {this, int} | {int}
0003: i2l // {this, int} | {long, top}
0004: lstore_2 // {this, int, long, top} | {}
0005: return // {} | {}
从 JVM 规范的角度来看,i2l
指令对应的 Operand Stack 的变化如下:
..., value →
..., result
The value on the top of the operand stack must be of type int
. It is popped from the operand stack and sign-extended to a long
result. That result
is pushed onto the operand stack.
long to int
从 Java 语言的视角,有一个 HelloWorld
类,代码如下:
public class HelloWorld {
public void test() {
long longValue = 0;
int intValue = (int) longValue;
}
}
从 Instruction 的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: lconst_0
1: lstore_1
2: lload_1
3: l2i
4: istore_3
5: return
}
从 ASM 的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(LCONST_0);
methodVisitor.visitVarInsn(LSTORE, 1);
methodVisitor.visitVarInsn(LLOAD, 1);
methodVisitor.visitInsn(L2I);
methodVisitor.visitVarInsn(ISTORE, 3);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(2, 4);
methodVisitor.visitEnd();
从 Frame 的视角来看,local variable 和 operand stack 的变化:
// {this} | {}
0000: lconst_0 // {this} | {long, top}
0001: lstore_1 // {this, long, top} | {}
0002: lload_1 // {this, long, top} | {long, top}
0003: l2i // {this, long, top} | {int}
0004: istore_3 // {this, long, top, int} | {}
0005: return // {} | {}
从 JVM 规范的角度来看,l2i
指令对应的 Operand Stack 的变化如下:
..., value →
..., result
The value
on the top of the operand stack must be of type long
. It is popped from the operand stack and converted to an int result
by taking the low-order 32 bits of the long value
and discarding the high-order 32 bits. The result
is pushed onto the operand stack.