I am trying to make fun of some services in my developing env. The serviceFactory code looks something like this:
public class ApiFacadeImpl implements ApiFacade {
private OneService oneService = null;
public OneService getOneService(){
if(oneService==null) {
return oneService;
}
}
I know that this factory is not very well coded and designed. However, I cannot change its code. my idea is to change the bytecode, so I can redefine it like this:
public class ApiFacadeImpl implements ApiFacade {
private OneService oneService = new MyMockOneService();
....
}
My first: is this possible with javassist? And How?
Since I cannot find something like reinitializing a field using javassist using google, I tried it myself by deleting it and re-creating it:
CtField oneServiceField = cc.getDeclaredField("oneService");
cc.removeField(oneServiceField);
CtField f = CtField.make(String.format("private %s %s=new %s();",
oneServiceField.getType().getName(), "oneService",
mockClass.getCanonicalName()), cc);
cc.addField(f);
cc.toClass();
then I got an exception:
javassist.CannotCompileException: by java.lang.ClassFormatError: Invalid length 99 in LocalVariableTable in class file com/Test
at javassist.ClassPool.toClass(ClassPool.java:1051)
at javassist.ClassPool.toClass(ClassPool.java:994)
at javassist.ClassPool.toClass(ClassPool.java:952)
at javassist.CtClass.toClass(CtClass.java:1079)
My second question is why is this an exception? What is the definition of an incomprehensible class java class? And when I delete the field, javassist helps to remove the field link in:
public OneService getOneService(){
if(oneService==null) {
return oneService;
}
Many thanks.
source