How to change the initial value of a field using javassist

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) {//some initialization steps }
        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) {//some initialization steps }
        return oneService;
    }

Many thanks.

+5
source
1

№1, , ApiFacadeImpl. CtConstructor#insertAfter .

ClassPool pool = ClassPool.getDefault();
CtClass factoryClass = pool.getCtClass("ServiceFactory");
CtConstructor constructor = factoryClass.getDeclaredConstructor(null);
String setMockStatement = String.format("service = new %s();",
        MockServiceImpl.class.getCanonicalName());
constructor.insertAfter(setMockStatement);
factoryClass.toClass();
new ServiceFactory().getService().say();

, . . , , . , . , service MockServiceImpl, null. , javassist.

javassist-3.14.0-GA - Problm removeField addField, CtField.make

№2 , . javassist? mockClass? javassist?

Javassist java.lang.ClassFormatError: 561 LocalVariableTable

+4

All Articles