2016-12-18 17 views
1

Я хочу использовать javassist (версия 3.19-GA) для генерации байт-кода статического инициализатора класса, который запускает поток. По какой-то причине я не могу понять, что джавассист ожидает «;» где-то, хотя я считаю, что код, который я предоставляю, синтаксически корректен. Кто-то видит больше, чем я? Вот код. В чем проблема?Ошибка синтаксиса при добавлении Runnable в статическом инициализаторе с javassist

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) 

Спасибо за любую подсказку.

ответ

0

Из официальной документации void insertAfter(String src):

Параметры:

ЦСИ - исходный код, представляющий вставленный байткод. Это должен быть один оператор или блок .

В вашем srcString параметра, вы не обеспечиваете одного заявления или блок.
Блок "{}".

Попробуйте insertBefore(String src) метод с глобальным ограждающих "{}":

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

Не помогает, к сожалению. Сообщение об ошибке одно и то же. Похоже, что конструкция с анонимным классом здесь невозможна. – kaidentity

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); 
    } 
}