(Originally posted here)
I took my very first step with Javassist by writing a SSCCE that tries to modify a field access. It compiles and runs without error, but the output is not what I expected.
package test;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.expr.ExprEditor;
import javassist.expr.FieldAccess;
public class Test1 {
public static void main(String[] args) {
try {
// instrument the class
final CtClass ctClass = ClassPool.getDefault().get(Foo.class.getName());
final CtMethod ctMethod = ctClass.getDeclaredMethod("setValue");
ctMethod.instrument(new ExprEditor() {
@Override
public void edit(FieldAccess f) throws CannotCompileException {
//System.out.printf("instrumenting field access in %s, line %d\n", f.getFileName(), f.getLineNumber());
f.replace("System.out.println(\"fnord\");");
}
});
// test the instrumentation
Foo foo = new Foo();
foo.setValue(42);
System.out.println(foo.getValue());
}
catch (NotFoundException | CannotCompileException e) {
e.printStackTrace();
}
}
}
package test;
public class Foo {
private int value;
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
I expected the output to be:
fnord
0
...because I expected that the field assignment would be replaced by the code that prints "fnord", and the value would remain uninitialized. But instead, the output is:
42
The code that attempts to replace the field assignment definitely runs and operates on the correct line, as I can see if I uncomment the print statement there. What am I doing wrong?