我正在尝试使用字节码检测来添加try catch块。
所以基本上,我有一堂“狮子”。我想在try块中捕获其方法“ stayLion()”之一的全部内容并给出相应的捕获。
为此,我在转换方法中使用了method.addCatch()。一切正常,除了我尝试在catch块“ TestDebug test = new TestDebug()”中添加此语句时。我无法创建自己定义的类的对象。
另外,还有其他更简单的过程来使用BCI在try catch块中捕获方法主体吗?
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)
最佳答案
为了在Javaassist中使用某些类,您需要指定完整的软件包名称。
代替TestDebug test = new TestDebug();
采用
com.javapapers.java.instrumentation.TestDebug test = new com.javapapers.java.instrumentation.TestDebug();