将 java 代理与可操纵的 java 字节码 (ASM) 结合使用

问题描述 投票:0回答:1

A Guide to Java Bytecode Manipulation with ASM的帮助下,我试图弄清楚ASM是如何工作的。我按照教程为 Integer 类创建了一个“额外”静态字段。这是 Instrumentation 类的简化逻辑:

public static void premain(String agentArgs, Instrumentation inst) {
  inst.addTransformer(new ClassFileTransformer() {
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, final byte[] buffer) {
      if (className.equals("ClassX")) {
        var reader = new ClassReader(bytes);
        var writer = new ClassWriter(reader, 0);
        var visitor = new ClassVisitor() { // simplified
          @Override
          public void visitEnd() {
            if (!isFieldPresent) {
              var fv = cv.visitField(ACC_PUBLIC + ACC_STATIC, "aNewBooleanField", BOOLEAN_TYPE.toString(), null, true);
              if (fv != null) fv.visitEnd();
            }
            cv.visitEnd();
          }
        };
        reader.accept(visitor, 0);
        return writer.toByteArray();
      }
      return buffer;
    }
  });
}

我用maven打包了ASM代码;现在我正在尝试运行它,但我不知道如何使用它。我希望我应该能够做到这样的事情:

public static void main(String[] args) {
    System.out.println(ClassX.aNewBooleanField);
}

这当然不会编译,因为编译器不知道额外的字段。我尝试按照教程的建议添加 java agent¹,但我也不明白。编译器如何知道在运行时运行的进程(代理)?

所以底线问题是,我如何使用 ASM 操纵代码?


¹

-javaagent:"/<path>/.m2/repository/org/example/try-asm/1.0-SNAPSHOT/try-asm-1.0-SNAPSHOT.jar"

java java-bytecode-asm bytecode-manipulation
1个回答
0
投票

如问题所述,编译器确实不知道对类的字节码所做的修改。因此,您不能直接调用

ClassX.aNewBooleanField
。因此你需要回归反思:

var modifiedClass = Class.forName("ClassX");
var field = modifiedClass.getField("aNewBooleanField");
System.out.println(field.getBoolean(null));

您现在可以编译您的代码,您可以使用 java 代理运行它,上面的代码将打印出

true
值!

© www.soinside.com 2019 - 2024. All rights reserved.