Java 代码生成宽指令

Which Java code generates Wide instruction

我正在创建一个 JVM 并试图理解字节码指令。我正在尝试编写 java 代码,该代码在编译时会生成一个 .class 具有宽指令的文件。哪个 java 代码会生成那种扩展指令?我对广泛的行为有点迷茫

作为the JVMspec says:

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 […]. The second form applies only to the iinc instruction[…].

因此,wide 指令用于编码加载或存储变量的指令,其索引不能用单个 byte 寻址,即高于 255,或 iinc 指令有一个变量索引或一个 int 偏移量,不适合一个字节。

对于前者,我们必须声明尽可能多的局部变量来触发匹配wide指令的生成,对于后者,只要足够大的增量值就足够了:

class WideInstruction {
    public static void largeIncrement(int i) { i += 1000; }
    public static int largeVarIndex() {
        int i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18,
        i19, i20, i21, i22, i23, i24, i25, i26, i27, i28, i29, i30, i31, i32, i33, i34, i35,
        i36, i37, i38, i39, i40, i41, i42, i43, i44, i45, i46, i47, i48, i49, i50, i51, i52,
        i53, i54, i55, i56, i57, i58, i59, i60, i61, i62, i63, i64, i65, i66, i67, i68, i69,
        i70, i71, i72, i73, i74, i75, i76, i77, i78, i79, i80, i81, i82, i83, i84, i85, i86,
        i87, i88, i89, i90, i91, i92, i93, i94, i95, i96, i97, i98, i99, j0, j1, j2, j3, j4,
        j5, j6, j7, j8, j9, j10, j11, j12, j13, j14, j15, j16, j17, j18, j19, j20, j21, j22,
        j23, j24, j25, j26, j27, j28, j29, j30, j31, j32, j33, j34, j35, j36, j37, j38, j39,
        j40, j41, j42, j43, j44, j45, j46, j47, j48, j49, j50, j51, j52, j53, j54, j55, j56,
        j57, j58, j59, j60, j61, j62, j63, j64, j65, j66, j67, j68, j69, j70, j71, j72, j73,
        j74, j75, j76, j77, j78, j79, j80, j81, j82, j83, j84, j85, j86, j87, j88, j89, j90,
        j91, j92, j93, j94, j95, j96, j97, j98, j99, k0, k1, k2, k3, k4, k5, k6, k7, k8, k9,
        k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k20, k21, k22, k23, k24, k25, k26,
        k27, k28, k29, k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k40, k41, k42, k43,
        k44, k45, k46, k47, k48, k49, k50, k51, k52, k53, k54, k55, k56, k57 = 42;

        return k57;
    }
    public static void main(String[] args) {
        decompile();
    }
    private static void decompile() {
        try {
        new ProcessBuilder(
                Paths.get(System.getProperty("java.home"), "bin", "javap").toString(),
                "-cp", System.getProperty("java.class.path"),
                "-c", MethodHandles.lookup().lookupClass().getName())
                .inheritIO().start().waitFor();
        } catch(IOException | InterruptedException ex) {}
    }
    private WideInstruction() {}
}

有趣的是,javap 不打印 wide iinc 也不打印 wide iloadwide istore,而是 iinc_wiload_wistore_w。但这只是证明没有“Java字节码汇编语言”标准。

Compiled from "WideInstruction.java"
class WideInstruction {
  public static void largeIncrement(int);
    Code:
       0: iinc_w        0, 1000
       6: return

  public static int largeVarIndex();
    Code:
       0: bipush        42
       2: istore_w      256
       6: iload_w       256
      10: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: invokestatic  #1                  // Method decompile:()V
       3: return
}