【问题标题】:Which Java code generates Wide instruction哪个 Java 代码生成宽指令
【发布时间】:2020-03-23 05:07:59
【问题描述】:

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

【问题讨论】:

    标签: java jvm bytecode instruction-set jvm-bytecode


    【解决方案1】:

    作为the JVMspec says:

    wide 指令修改另一条指令的行为。它采用两种格式之一,具体取决于正在修改的指令。 wide 指令的第一种形式修改了一个指令 iloadfloadaloadlload dloadistorefstoreastorelstoredstoreret […]。第二种形式仅适用于 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 iincwide iload resp。 wide 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
    }
    

    【讨论】:

    • 我很难理解那个很宽的索引。我用 jclasslib 打开了你的代码,它完美地显示了所有的宽度!谢谢!
    • 是的,在加载和存储指令的情况下是索引,在iinc的情况下是索引和常量值。
    • 附带说明,如果您想要 Java 字节码反汇编,我强烈建议使用 Krakatau。它不会像 javap 那样隐藏或破坏东西,它使用的程序集格式非常直接地映射到类文件格式。 github.com/Storyyeller/Krakatau
    • 感谢您的回答。我为理解广泛的指导而苦苦挣扎。
    猜你喜欢
    • 2020-04-29
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2011-07-09
    • 1970-01-01
    相关资源
    最近更新 更多