2016-07-25 70 views
0

我正在与ASM打交道,因为5天后我无法获得解决方案以解决问题。要求是通过方法调用获取所有作为参数传递的值。我知道有很多工具可以做到这一点。我去了ASM(我不知道如果我把正确的决定)ASM Bytecode将值作为参数传递给某些方法的调用

举例来说,如果我有这些方法

 public void test2(String a, int b , String c, boolean ba, long d, String e){ 

     } 
    public String giveMeAString(){ 
     return "oneString"; 
    } 

    public String giveMeAnotherString(){ 
     return "anotherString"; 
    } 

    public void test(){ 
     test2("firstParameter", 2907, giveMeAString(),true, 1992, giveMeAnotherString()); 
    } 

我想保存 [“firstParameter”,2907“ oneString”,真正的,1992年, “anotherString”]

我已阅读下列主题:

How to get the return value in asm?

Java method parameters values in ASM

Tracing method invocation arguments in bytecode using ASM

get function arguments values using java asm for bytecode instrimentation

其中关于把参数传递给本地变量解释,但我怎么能访问它们?

如何获得该参数的值?我不明白我怎么能得到这个参数..我不知道,例如打印它们。任何想法? 一旦他们在堆栈中,我不明白如何将值复制到一个变量。

谢谢!

这里是我正在使用的代码:

public static class ClassPrinterVisitor extends ClassVisitor { 
    private String name; 
    private String desc; 
    private String signature; 

    private Type[] paramTypes; 
    private boolean isStatic; 
    private String className; 
    private String methodName; 
    private String methodDesc; 
    private String owner; 
    private int access; 

    public ClassPrinterVisitor(int api, ClassVisitor cv) { 
     super(api, cv); 
    } 

    public ClassPrinterVisitor(int api) { 
     super(api); 
    } 


    @Override 
    public MethodVisitor visitMethod(int access, String name, String desc, 
            String signature, String[] exceptions) { 

     MethodVisitor oriMv = new MethodVisitor(Opcodes.ASM4) { 
     }; 

     final MethodVisitor instMv2 = new MethodPrinterVisitor(access, desc, oriMv, Type.getArgumentTypes(desc), (access & Opcodes.ACC_STATIC) != 0, className, 
       name, desc); 
     return instMv2; 
    } 


    private class MethodPrinterVisitor extends MethodVisitor { 

     List<Object> params = new ArrayList<>(); 
     List<Object> params2 = new ArrayList<>(); 

     private Type[] paramTypes; 
     private boolean isStatic; 
     private String className; 
     private String methodName; 
     private String methodDesc; 

     public MethodPrinterVisitor(int api, MethodVisitor mv) { 
      super(api, mv); 
     } 


     public MethodPrinterVisitor(int access, String desc, MethodVisitor mv, Type[] paramTypes, boolean isStatic, String classname, 
            String methodname, String methoddesc) { 
      super(Opcodes.ASM4, mv); 
      this.paramTypes = paramTypes; 
      this.isStatic = isStatic; 
      this.className = classname; 
      this.methodName = methodname; 
      this.methodDesc = methoddesc; 

     } 


     @Override 
     public void visitLdcInsn(Object var1) { 
      if (var1 != null) { 
       params.add(var1); 
       super.visitLdcInsn(var1); 
       System.out.printf("arg: %s %n", var1.toString()); 

      } 

     } 
     @Override 
     public void visitInsn(int var1) { 
      if(this.mv != null) { 
       this.mv.visitInsn(var1); 
      } 

     } 
     @Override 
     public void visitIntInsn(int var1, int var2) { 
      if(this.mv != null) { 
       this.mv.visitIntInsn(var1, var2); 
      } 

     } 
     @Override 
     public void visitVarInsn(int var1, int var2) { 
      if(this.mv != null) { 
       this.mv.visitVarInsn(var1, var2); 
      } 

     } 

     @Override 
     public void visitMethodInsn(int opcode, String owner, String name, String desc) { 
      Pattern pattern = Pattern.compile("[a-zA-Z0-9._]*"); 

      System.out.printf("---------------------------%n"); 
      System.out.printf("Class %s calls method %s from class %s%n", ClassPrinterVisitor.this.name, name, owner); 
      System.out.printf("Desc: %s signature: %s%n", ClassPrinterVisitor.this.desc, ClassPrinterVisitor.this.signature); 
      for (Object p : params) { 
       Matcher matcher = pattern.matcher(p.toString()); 
       if (!p.toString().isEmpty() && !p.toString().startsWith(".") && matcher.matches()) { 
        System.out.printf("visitLdcInsn: %s %n", p); 
       } 
      } 
      System.out.printf("---------------------------%n%n"); 
      params = new ArrayList<>(); 
     } 

     @Override 
     public void visitCode() { 
      int paramLength = paramTypes.length; 

      // Create array with length equal to number of parameters 
      mv.visitIntInsn(Opcodes.BIPUSH, paramLength); 
      mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object"); 
      mv.visitVarInsn(Opcodes.ASTORE, paramLength); 

      // Fill the created array with method parameters 
      int i = 0; 
      for (Type tp : paramTypes) { 
       mv.visitVarInsn(Opcodes.ALOAD, paramLength); 
       mv.visitIntInsn(Opcodes.BIPUSH, i); 

       if (tp.equals(Type.BOOLEAN_TYPE)) { 
        mv.visitVarInsn(Opcodes.ILOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;"); 
       } else if (tp.equals(Type.BYTE_TYPE)) { 
        mv.visitVarInsn(Opcodes.ILOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;"); 
       } else if (tp.equals(Type.CHAR_TYPE)) { 
        mv.visitVarInsn(Opcodes.ILOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;"); 
       } else if (tp.equals(Type.SHORT_TYPE)) { 
        mv.visitVarInsn(Opcodes.ILOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;"); 
       } else if (tp.equals(Type.INT_TYPE)) { 
        mv.visitVarInsn(Opcodes.ILOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;"); 
       } else if (tp.equals(Type.LONG_TYPE)) { 
        mv.visitVarInsn(Opcodes.LLOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;"); 
        i++; 
       } else if (tp.equals(Type.FLOAT_TYPE)) { 
        mv.visitVarInsn(Opcodes.FLOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;"); 
       } else if (tp.equals(Type.DOUBLE_TYPE)) { 
        mv.visitVarInsn(Opcodes.DLOAD, i); 
        mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;"); 
        i++; 
       } else 
        mv.visitVarInsn(Opcodes.ALOAD, i); 

       mv.visitInsn(Opcodes.AASTORE); 
       i++; 
      } 

      // Load id, class name and method name 
      this.visitLdcInsn(new Integer(this.methodID)); 
      this.visitLdcInsn(this.className); 
      this.visitLdcInsn(this.methodName); 

      // Load the array of parameters that we created 
      this.visitVarInsn(Opcodes.ALOAD, paramLength); 


      mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, signature); 
      super.visitCode(); 
     } 


    } 

} 

回答

0

你不能“得上的一些方法调用的参数传递的值”使用ASM访问的方法的字节码的时候,我想你可能有错误地理解这些参考。

ASM只是一个用于字节码操作的库。在对方法进行操作期间,字节码中显示的数字只是局部变量索引(参数和局部变量),您无法获取变量引用的VALUE(如果它不是常量)。

唯一可能获得这些局部变量索引的值是执行访问的字节码。一个方法的字节码是静态的,这些变量索引引用的值是UNKNOWN。当执行方法的字节码时,这些索引引用一些对象,并且VM知道它。

相关问题