我正在创建一个JVM并试图了解字节码指令。我正在尝试编写Java代码,该代码在编译时会生成带有宽指令的.class文件。哪种Java代码会生成这种扩展指令?我对行为举止有些迷茫
答案 0 :(得分:4)
wide 指令修改了另一条指令的行为。它采用两种格式之一,具体取决于要修改的指令。 wide 指令的第一种形式修改了 iload , fload , aload , lload中的一条指令, dload , istore , fstore , astore , lstore , dstore 或 ret […]。第二种形式仅适用于 iinc 指令[…]。
因此,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 iload
。 wide istore
,而是iinc_w
,iload_w
和istore_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
}