概览
从 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,inegladd,lsub,lmul,ldiv,lrem,lnegfadd,fsub,fmul,fdiv,frem,fnegdadd,dsub,dmul,ddiv,drem,dnegishl,ishr,iushr,iand,ior,ixor(int 类型的位操作)lshl,lshr,lushr,land,lor,lxor(long 类型的位操作)i2l,i2f,i2d,i2b,i2c,i2sl2i,l2f,l2df2i,f2l,f2dd2i,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.