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
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
}