javajvmbytecodeinstruction-setjvm-bytecode

Which Java code generates Wide instruction


I am creating a JVM and trying to understand the bytecode instructions. I am trying to write java code that when compiled generates a .class file with wide instruction. Which java code would generate that kind of extended instruction? I am a little bit lost with the wide behavior


Solution

  • As 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[…].

    So, the wide instruction is used to encode instructions loading or storing variables with an index not addressable with a single byte, i.e. higher than 255, or an iinc instruction with either, a variable index or an int offset, not fitting into a byte.

    For the former, we have to declare as many local variable to trigger the generation of a matching wide instruction, for the latter, just a large enough increment value would suffice:

    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() {}
    }
    

    Interestingly, javap doesn’t print wide iinc nor wide iload resp. wide istore, but rather, iinc_w, iload_w, and istore_w. But that just demonstrates that there is no “Java Bytecode Assembly Language” standard.

    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
    }