javassist icon indicating copy to clipboard operation
javassist copied to clipboard

When set body of Method/Constructor, the parameter names are lost

Open teras opened this issue 7 years ago • 4 comments

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.

teras avatar Aug 31 '17 23:08 teras

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)?

teras avatar Sep 01 '17 07:09 teras

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.

nickl- avatar Nov 13 '17 00:11 nickl-

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.

teras avatar Jan 24 '18 14:01 teras

 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);
            }
        }
    }

roseboy avatar Aug 01 '19 05:08 roseboy