上级目录

概览

从 Instruction 的角度来说,与 wide 相关的 opcode 有 1 个,内容如下:

opcode mnemonic symbol opcode mnemonic symbol opcode mnemonic symbol opcode mnemonic symbol
196 wide            

从 ASM 的角度来说,这 wide 指令并没有与特定的 MethodVisitor.visitXxxInsn() 方法对应。

The wide instruction modifies the behavior of another instruction. It takes one of two formats, depending on the instruction being modified.

The first form of the wide instruction modifies one of the instructions iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, or ret.

wide
<opcode>
indexbyte1
indexbyte2

where <opcode> is one of iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, or ret.

The second form of the wide instruction applies only to the iinc instruction.

wide
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2

另外,与 wide 相关的 opcode 有 ldc_wldc2_wgoto_wjsr_w(已经弃用)。

wide: istore

从 Java 语言的视角,有一个 HelloWorld 类,代码如下:

public class HelloWorld {
    public void test() {
        int var001 = 1;
        // ... ... 省略
        int var257 = 257;
    }

    public static void main(String[] args) {
        String format = "int var%03d = %d;";
        for (int i = 1; i < 258; i++) {
            String line = String.format(format, i, i);
            System.out.println(line);
        }
    }
}

从 Instruction 的视角来看,方法体对应的内容如下:

$ javap -c -p 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
       ...
    1140: sipush        256
    1143: istore_w      256
    1147: sipush        257
    1150: istore_w      257
    1154: return

...
}

但是,istore_w 并不是真实存在的 opcode,它其实是 wideistore 指令的组合之后的结果,如下所示:

=== === ===  === === ===  === === ===
0000: iconst_1             // 04
0001: istore_1             // 3C
0002: iconst_2             // 05
0003: istore_2             // 3D
...
1140: sipush          256  // 110100
1143: wide                 // C4
1144: istore          256  // 360100
1147: sipush          257  // 110101
1150: wide                 // C4
1151: istore          257  // 360101
1154: return               // B1

从 ASM 的视角来看,方法体对应的内容如下:

methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_1);
methodVisitor.visitVarInsn(ISTORE, 1);
methodVisitor.visitInsn(ICONST_2);
methodVisitor.visitVarInsn(ISTORE, 2);
...
methodVisitor.visitIntInsn(SIPUSH, 255);
methodVisitor.visitVarInsn(ISTORE, 255);
methodVisitor.visitIntInsn(SIPUSH, 256);
methodVisitor.visitVarInsn(ISTORE, 256);
methodVisitor.visitIntInsn(SIPUSH, 257);
methodVisitor.visitVarInsn(ISTORE, 257);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(1, 258);
methodVisitor.visitEnd();

wide: iinc

当使用 iinc 时,如果 local variable 值的变化范围大于 127 或者小于 -128,就会生成 wide 指令。

从 Java 语言的视角,有一个 HelloWorld 类,代码如下:

public class HelloWorld {
    public void test(int val) {
        val += 128;
    }
}

从 Instruction 的视角来看,方法体对应的内容如下:

$ javap -c -p sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
  public void test(int);
    Code:
       0: iinc_w        1, 128
       6: return
}

但是,iinc_w 并不是真实存在的 opcode,它其实是 wideiinc 指令的组合之后的结果,如下所示:

=== === ===  === === ===  === === ===
0000: wide                 // C4
0001: iinc       1    128  // 8400010080
0006: return               // B1
=== === ===  === === ===  === === ===
LocalVariableTable:
index  start_pc  length  name_and_type
    0         0       7  this:Lsample/HelloWorld;
    1         0       7  val:I

从 ASM 的视角来看,方法体对应的内容如下:

methodVisitor.visitCode();
methodVisitor.visitIincInsn(1, 128);
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(0, 2);
methodVisitor.visitEnd();

从 Frame 的视角来看,local variable 和 operand stack 的变化:

                               // {this, int} | {}
0000: wide                
0001: iinc       1    128      // {this, int} | {}
0006: return                   // {} | {}