【问题标题】:javassist.CannotCompileException: [source error] no such class: TestDebugjavassist.CannotCompileException:[源错误]没有这样的类:TestDebug
【发布时间】:2017-06-27 09:14:31
【问题描述】:

我正在尝试使用字节码检测添加 try catch 块

所以基本上,我有一个班级“狮子”。我想在 try 块中捕获其方法“stayLion()”之一的全部内容并给出相应的捕获。

为此,我在 transform 方法中使用了 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)

【问题讨论】:

  • = new com.javapapers.java.instrumentation.TestDebug()代替初始化怎么样?
  • 没有帮助。我尝试过类似的变体,但没有用。 Integer i = new Integer(10) 有效。所以我确信我犯了一个类似的错误,但我到底在哪里找不到。
  • 你有没有声明过classPool.importPackage("com.javapapers.java.instrumentation");somewhere ?
  • 不,我没有。我无法准确理解这在哪里以及为什么相关。我应该把它放在哪里?既然所有的类都在同一个包中,那为什么会相关呢?
  • ClassPool classPool = ClassPool.getDefault(); 行之后。好吧,更好的问题是为什么你纯粹在 Strings 中运行一些代码?普通代码不会有问题。原因是,因为您使用了一些具有这些要求的框架。另请查看jboss-javassist.github.io/javassist/tutorial/…中的第 4.6 点

标签: java bytecode instrumentation javassist


【解决方案1】:

为了在 Javaassist 中使用某些类,您需要指定完整的包名。

代替

TestDebug test = new TestDebug();

使用

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-11
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多