Почему я должен вызывать .toClass() после изменения тела метода с помощью Javassist?

Я изменяю тело метода getMessage() моего TestClass с помощью Javassist следующим образом:

ClassPool cp = new ClassPool(true);
CtClass ctClass = cp.get("my.test.javassist.TestClass");
CtMethod ctMethod = ctClass.getDeclaredMethod("getMessage");
ctMethod.setBody("{ return \"Hello from javassist\"; }");
ctClass.toClass();

TestClass c = new TestClass();
System.out.println(c.getMessage());

Это работает хорошо. Однако, если я удалю вызов метода ctClass.toClass(), подстановка тела не сработает. Почему?

Как мне правильно заменить тело моего метода getMessage()? Я делаю это правильно?


person Michal Vician    schedule 12.09.2011    source источник


Ответы (1)


ClassPool содержит CtClass объектов - они представляют классы, но они не классы Java. Методы toClass() преобразуют CtClass экземпляров в классы Java и фактически загружают класс.

Если вы не выполните toClass(), то изменения байтового кода не будут скомпилированы в класс, а new TestClass() вызовет загрузку класса из пути к классам.

person Andreas Dolk    schedule 12.09.2011
comment
Спасибо @Andreas_D. Таким образом, стандартный подход состоит в том, чтобы изменить объекты CtClass и после всех модификаций «зафиксировать» изменения, вызвав toClass(), верно? - person Michal Vician; 12.09.2011
comment
@miso - это мое понимание :) И я почти уверен, что мы не можем вносить изменения после загрузки класса. Таким образом, если вы создадите экземпляр TestClass до вызова toClass(), произойдет сбой. Просто потому, что JVM не может перезагрузить класс. - person Andreas Dolk; 12.09.2011
comment
На самом деле перезагрузка частей классов возможна с помощью интерфейсов отладчика (например, Eclipse может изменять методы существующих объектов). Однако я не знаю, поддерживает ли это Javassist. - person Paŭlo Ebermann; 12.09.2011
comment
Это HCR (горячая замена кода), специальный метод отладки (с использованием различных JVM и канала отладки). ) - person Andreas Dolk; 12.09.2011