使用javassist在静态初始化程序中添加Runnable时出现语法错误

时间:2016-12-18 09:41:08

标签: javassist

我想使用javassist(版本3.19-GA)生成启动线程的类的静态初始化程序的字节码。出于某种原因,我无法理解javassist期望&#34 ;;"即使我相信我提供的代码在语法上是正确的。有人看到的比我多吗?这是代码。有什么问题?

ClassPool pool = ClassPool.getDefault();
final CtClass clazz = pool.get(somename);
clazz.makeClassInitializer().insertAfter(
   "try{Runnable r=new Runnable () {public void run () { System.out.println (\"hello!!!!\"); }}; " +
   "new Thread(r).start(); } catch(Exception e){}");

我收到以下异常:

javassist.CannotCompileException: [source error] ; is missing
    at javassist.CtBehavior.insertAfter(CtBehavior.java:877)
    at javassist.CtBehavior.insertAfter(CtBehavior.java:792)
    at my.code(myclass.java:111)

感谢任何提示。

2 个答案:

答案 0 :(得分:1)

很可能javassist编译器不支持匿名内部类,如new Runnable () {...}

您必须创建新类,从Runnable继承它,实现方法run并在构造函数中创建此类的对象。

package hello;
import javassist.*;

class Test{
}

class Main {
    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        final CtClass clazz = pool.get(Test.class.getCanonicalName());

        CtClass runnable = pool.makeClass("my.custom.RunnableImpl");
        runnable.addInterface(pool.get("java.lang.Runnable"));
        CtMethod method = CtNewMethod.make("public void run() { System.out.println(\"hello!!!!\"); }", runnable);
        runnable.addMethod(method);

        // load class
        runnable.toClass();

        clazz.setName("newTest");
        CtConstructor ctConstructor = clazz.makeClassInitializer();
        ctConstructor.insertAfter("try{ new Thread( new my.custom.RunnableImpl() ).start(); } catch(Exception e){}");
        Class aClass = clazz.toClass();

        // call initializer
        Class.forName(aClass.getCanonicalName());
        Thread.sleep(1000);
    }
}

答案 1 :(得分:0)

来自void insertAfter(String src)的正式文件:

<强>参数

  

src - 表示插入的字节码的源代码。它必须是一个   单一陈述或阻止。

src String参数中,您不提供单个语句或块。
一个块是"{}"

尝试使用全局封闭insertBefore(String src)的{​​{1}}方法:

"{}"