2017-02-09 2 views
0

J'essaie d'ajouter un bloc try catch en utilisant l'instrumentation bytecode.javassist.CannotCompileException: [erreur source] pas une telle classe: TestDebug

Donc, fondamentalement, j'ai une classe 'Lion'. Je veux capturer le contenu entier de l'une de ses méthodes 'stayLion()' dans try block et donner un catch correspondant. Pour cela, j'ai utilisé method.addCatch() dans la méthode de transformation. Pour cela, j'ai utilisé method.addCatch(). Les choses marchent bien, sauf lorsque j'essaie d'ajouter cette instruction dans le bloc catch 'TestDebug test = new TestDebug()'. Je ne suis pas capable de créer un objet d'une classe définie par moi-même.

De même, existe-t-il un autre processus plus simple pour capturer le corps de la méthode dans le bloc try catch en utilisant BCI?

package com.javapapers.java.instrumentation; 

public class TestInstrumentation { 
    public static void main(String args[]) throws InterruptedException { 
     Lion l = new Lion(); 
     l.runLion(); 
     l.stayLion(); 
     System.out.println("The program has ended!"); 
    } 
} 

package com.javapapers.java.instrumentation; 

import java.io.Serializable; 

//to be instrumented java class 
public class Lion implements Serializable{ 
    public static int counter =0; 
    public String testing = "This is just to create an object. This is a final testing!!!"; 
    public void runLion() throws InterruptedException { 
     counter++; 
     System.out.println("Lion is going to run........!!!"); 
     Thread.sleep(2000L); 
    } 


    public void stayLion() throws InterruptedException{ 
     counter++; 
     int arr[] = {1,2,3,4}; 
     System.out.println("The element is " + arr[4]);   //this error is done intentionally to have the catch block implemented 
     System.out.println("Lion is going to stay.......!!!"); 
     Thread.sleep(2000L); 
    } 

} 

package com.javapapers.java.instrumentation; 

import java.io.ByteArrayInputStream; 
import java.lang.instrument.ClassFileTransformer; 
import java.lang.instrument.IllegalClassFormatException; 
import java.security.ProtectionDomain; 

import javassist.ClassPool; 
import javassist.CtClass; 
import javassist.CtMethod; 

//this class will be registered with instrumentation agent 
public class DurationTransformer implements ClassFileTransformer { 
    public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, 
      ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { 
     byte[] byteCode = classfileBuffer; 


     if (className.equals("com/javapapers/java/instrumentation/Lion")) { 
      System.out.println("Instrumenting......"); 
      try { 
       ClassPool classPool = ClassPool.getDefault(); 
       CtClass ctClass = classPool.makeClass(new ByteArrayInputStream(classfileBuffer)); 
       CtMethod[] methods = ctClass.getDeclaredMethods(); 
       for (CtMethod method : methods) { 
        method.addLocalVariable("startTime", CtClass.longType); 
        method.insertBefore("startTime = System.nanoTime();"); 
        method.insertAfter("System.out.println(\"Execution Duration " 
          + "(nano sec): \"+ (System.nanoTime() - startTime));"); 
        method.insertAt(6, "System.out.println(\"This is a success!!!\");"); 
        if(method.getName().equals("stayLion")) 
        { 
         CtClass etype = ClassPool.getDefault().get("java.lang.Exception"); 
         method.addCatch("{ System.out.println(\"We have caught the error via Transformer\"); " 
           + "TestDebug test = new TestDebug();"  //The error is here. Not able to create TestDebug object 
           + "test.saveState(this);" 
           + "throw $e; }", etype); 
        } 
       } 
       byteCode = ctClass.toBytecode(); 
       ctClass.detach(); 
       System.out.println("Instrumentation complete."); 
      } catch (Throwable ex) { 
       System.out.println("Exception: " + ex); 
       ex.printStackTrace(); 
      } 
     } 
     return byteCode; 
    } 
} 

package com.javapapers.java.instrumentation; 

import java.lang.instrument.Instrumentation; 

public class DurationAgent { 

    // for all the class loaded, premain will be called 
    public static void premain(String agentArgs, Instrumentation inst) { 
     System.out.println("Executing premain........."); 
     inst.addTransformer(new DurationTransformer()); 
    } 
} 

package com.javapapers.java.instrumentation; 

import java.io.File; 
import java.io.IOException; 
import org.codehaus.jackson.JsonGenerationException; 
import org.codehaus.jackson.map.JsonMappingException; 
import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.map.SerializationConfig; 


public class TestDebug { 

    public TestDebug(){ 
     System.out.println("We are in constructor"); 
    } 

    public static void saveState(Object emp){ 

     ObjectMapper mapper = new ObjectMapper(); 
     //mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); 
     try { 
      mapper.writeValue(new File("savedState.json"), emp); 
     } catch (JsonGenerationException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (JsonMappingException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
    } 
} 

============== ============================================= ================

Exception: javassist.CannotCompileException: [source error] no such class: TestDebug 
javassist.CannotCompileException: [source error] no such class: TestDebug 
     at javassist.CtBehavior.insertAt(CtBehavior.java:1146) 
     at javassist.CtBehavior.insertAt(CtBehavior.java:1073) 
     at com.javapapers.java.instrumentation.DurationTransformer.transform(DurationTransformer.java:38) 
     at sun.instrument.TransformerManager.transform(Unknown Source) 
     at sun.instrument.InstrumentationImpl.transform(Unknown Source) 
     at java.lang.ClassLoader.defineClass1(Native Method) 
     at java.lang.ClassLoader.defineClass(Unknown Source) 
     at java.security.SecureClassLoader.defineClass(Unknown Source) 
     at java.net.URLClassLoader.defineClass(Unknown Source) 
     at java.net.URLClassLoader.access$100(Unknown Source) 
     at java.net.URLClassLoader$1.run(Unknown Source) 
     at java.net.URLClassLoader$1.run(Unknown Source) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at java.net.URLClassLoader.findClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
     at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) 
     at java.lang.ClassLoader.loadClass(Unknown Source) 
     at com.javapapers.java.instrumentation.TestInstrumentation.main(TestInstrumentation.java:5) 
Caused by: compile error: no such class: TestDebug 
     at javassist.compiler.MemberResolver.searchImports(MemberResolver.java:447) 
     at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:412) 
     at javassist.compiler.MemberResolver.lookupClassByJvmName(MemberResolver.java:330) 
     at javassist.compiler.MemberResolver.resolveJvmClassName(MemberResolver.java:491) 
     at javassist.compiler.MemberCodeGen.resolveClassName(MemberCodeGen.java:1146) 
     at javassist.compiler.CodeGen.atDeclarator(CodeGen.java:711) 
     at javassist.compiler.ast.Declarator.accept(Declarator.java:99) 
     at javassist.compiler.CodeGen.atStmnt(CodeGen.java:350) 
     at javassist.compiler.ast.Stmnt.accept(Stmnt.java:49) 
     at javassist.compiler.Javac.compileStmnt(Javac.java:568) 
     at javassist.CtBehavior.insertAt(CtBehavior.java:1125) 
+0

Que diriez-vous en utilisant '= new com.javapapers.java.instrumentation.TestDebug()' la place pour l'initialisation? – DuKes0mE

+0

N'a pas aidé. J'ai essayé des variantes similaires, mais inutiles. 'Integer i = new Entier (10)' fonctionne. Donc, je suis sûr que je fais une erreur similaire, mais où est exactement ce que je ne parviens pas à savoir. – Gautam

+1

Avez-vous déjà déclaré 'classPool.importPackage (" com.javapapers.java.instrumentation ");' quelque part? – DuKes0mE

Répondre

0

pour utiliser certaines classes Javaassist, vous devez spécifier le nom complet de l'emballage.

Au lieu de

TestDebug test = new TestDebug();

utilisation

com.javapapers.java.instrumentation.TestDebug test = new com.javapapers.java.instrumentation.TestDebug();