2016-07-25 69 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知道它。

相關問題