2017-02-09 17 views
0

Я пытаюсь добавить блок catch try с помощью инструментария байт-кода.javassist.CannotCompileException: [исходная ошибка] нет такого класса: TestDebug

Итак, у меня есть класс «Лев». Я хочу захватить цельное содержимое одного из его методов «stayLion()» в блоке try и дать соответствующий catch.

Для этого я использовал метод method.addCatch() в методе преобразования. Все работает нормально, за исключением тех случаев, когда я пытаюсь добавить этот оператор в блок catch 'TestDebug test = new TestDebug()'. Я не могу создать объект моего собственного определенного класса.

Кроме того, есть ли другой более простой процесс для захвата тела метода в блоке try catch с использованием 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

Как об использовании '= новый com.javapapers.java.instrumentation.TestDebug()' вместо инициализации? – DuKes0mE

+0

Не помогло. Я пробовал подобные варианты, но бесполезно. 'Integer i = new Integer (10)' работает. Поэтому я уверен, что совершу подобную ошибку, но где именно я не могу это выяснить. – Gautam

+1

Вы когда-нибудь объявляли 'classPool.importPackage (" com.javapapers.java.instrumentation ");' где-то? – DuKes0mE

ответ

0

для того, чтобы использовать некоторые классы в Javaassist, необходимо указать полные имена пакетов.

Вместо

TestDebug test = new TestDebug();

использования

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