2016-07-25 21 views
0

Ich kämpfe mit ASM seit 5 Tagen und ich kann nicht mit der Lösung für mein Problem bekommen. Voraussetzung ist, dass alle Werte als Argumente von einem Methodenaufruf übergeben werden. Ich weiß, dass es viele Tools gibt, um das zu erreichen. Ich ging für ASM (ich weiß nicht, ob ich die richtige Entscheidung getroffen hat)ASM Bytecode Werte erhalten als Argumente bei Aufrufen einiger Methoden

Zum Beispiel, wenn ich diese Methoden haben

 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()); 
    } 

Ich möchte [ „firstParameter“, 2907 retten " oneString“, true, 1992, "anotherString"]

ich habe bereits diese Themen:

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

, die erklären, über die Argumente an die lokalen Variablen setzen, aber wie kann ich darauf zugreifen?

Wie kann ich die Werte dieser Argumente erhalten? Ich verstehe nicht, wie ich diese Argumente bekommen kann ... Ich weiß nicht, drucke sie zum Beispiel. Irgendeine Idee? Sobald sie im Stapel sind, verstehe ich nicht, wie der Wert in eine Variable kopiert werden kann.

Vielen Dank! Hier

ist der Code, den ich verwende:

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(); 
     } 


    } 

} 

Antwort

0

Sie können nicht „Werte als Argumente auf Anrufe einiger Methoden übergeben bekommen“, wenn eine Methode der Bytecode mit ASM besuchen, und ich denke, Sie haben könnten verstehe diese Verweise falsch.

ASM ist nur eine Bibliothek für die Bytecode-Manipulation. Während der Manipulation für eine Methode ist die im Bytecode angezeigte Zahl nur ein lokaler Variablenindex (Parameter und lokale Variablen), es gibt keine Möglichkeit, den Wert zu erhalten, den eine Variable referenziert (wenn sie nicht konstant ist).

Die VALUEs dieser lokalen Variablenindizes können nur abgerufen werden, indem der besuchte Bytecode ausgeführt wird. Der Bytecode einer Methode ist statisch und die Werte dieser Verweise auf Variablenindizes sind UNBEKANNT. Wenn sie den Bytecode einer Methode ausführen, verweisen diese Indizes auf einige Objekte, und die VM kennt sie.