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)
Que diriez-vous en utilisant '= new com.javapapers.java.instrumentation.TestDebug()' la place pour l'initialisation? – DuKes0mE
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
Avez-vous déjà déclaré 'classPool.importPackage (" com.javapapers.java.instrumentation ");' quelque part? – DuKes0mE