javassist
javassist copied to clipboard
When set body of Method/Constructor, the parameter names are lost
When manipulating the body of a method/constructor with the method setBody(String)
, the names of the parameter variables are lost.
For example a method public void test(String hello)
will become public void test(String s)
If any other manipulation is performed, the parameter names remain intact.
I have the feeling that this information is lost because setBody
removes all relative information from CodeAttribute, including LocalVariableAttribute.
At least to solve this problem, how can I explicitly put LocalVariableAttribute information back? (or at least, based on the existing information, create something from scratch)?
From the tutorial 4.2 Altering a method body
When using setBody
we use the following available special variables to reference parameters:
special variable | description |
---|---|
$0, $1, $2, ... | this and actual parameters |
$args | An array of parameters. The type of $args is Object[]. |
$$ | All actual parameters. |
Since setBody
replaces the existing body I see no need to restore the parameter names, unless I am missing something.
Sometimes IDEs rely on method parameter names, to provide useful information. This is the reason I'd like to keep names - an information completely lost otherwise.
private static void setBodyKeepParamInfos(CtMethod m, String src, boolean rebuild) throws CannotCompileException {
CtClass cc = m.getDeclaringClass();
if (cc.isFrozen()) {
throw new RuntimeException(cc.getName() + " class is frozen");
}
CodeAttribute ca = m.getMethodInfo().getCodeAttribute();
if (ca == null) {
throw new CannotCompileException("no method body");
} else {
CodeIterator iterator = ca.iterator();
Javac jv = new Javac(cc);
try {
int nvars = jv.recordParams(m.getParameterTypes(), Modifier.isStatic(m.getModifiers()));
jv.recordParamNames(ca, nvars);
jv.recordLocalVariables(ca, 0);
jv.recordReturnType(Descriptor.getReturnType(m.getMethodInfo().getDescriptor(), cc.getClassPool()), false);
//jv.compileStmnt(src);
//Bytecode b = jv.getBytecode();
Bytecode b = jv.compileBody(m, src);
int stack = b.getMaxStack();
int locals = b.getMaxLocals();
if (stack > ca.getMaxStack()) {
ca.setMaxStack(stack);
}
if (locals > ca.getMaxLocals()) {
ca.setMaxLocals(locals);
}
int pos = iterator.insertEx(b.get());
iterator.insert(b.getExceptionTable(), pos);
if (rebuild) {
m.getMethodInfo().rebuildStackMapIf6(cc.getClassPool(), cc.getClassFile2());
}
} catch (NotFoundException var12) {
throw new CannotCompileException(var12);
} catch (CompileError var13) {
throw new CannotCompileException(var13);
} catch (BadBytecode var14) {
throw new CannotCompileException(var14);
}
}
}