javastaticinstrumentationjavassistmodifiers

Javassist - Remove static modifier from method


I'm writing some Javassist code to intercept method calls and replace them with a proxy. To do that I'm using ExprEditor to replace the call in the following manner:

public static void main(String[] args) {

    try {

        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get("Test");
        CtMethod meth = ctClass.getDeclaredMethod("main");
        meth.instrument(new ExprEditor() {
            @Override
            public void edit(final MethodCall m) throws CannotCompileException {
                try {
                    if (m.getClassName().contains("Functions")) {

                        /* MAKE NON STATIC
                        CtClass old = pool.get(m.getClassName());
                        m.getMethod().setModifiers(Modifier.PUBLIC);
                        old.toClass();
                        */

                        String s = m.getClassName() + " proxy = (" +
                                m.getClassName() + ") " + Main.class.getName() + ".create(" + m.getClassName() + ".class);" +
                                " $_ = proxy." + m.getMethodName() + "($$);";
                        m.replace(s);

                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        Class clazz = ctClass.toClass();
        Method method = clazz.getMethod("main", String[].class);
        method.invoke(null, new Object[]{new String[]{}});

    } catch (InvocationTargetException e) {
        e.getCause().printStackTrace();
    } catch (NoSuchMethodException | IllegalAccessException | NotFoundException | CannotCompileException e) {
        e.printStackTrace();
    }
}

This works as desired as long as the method isn't static. Now I'm trying to change static methods to non static through the use of the commented code. It seems to me that this should work and there are similar usages in the Javassist docs for other modifiers, but when I uncomment and run it I get the following error message:

javassist.CannotCompileException: by java.lang.ClassFormatError: Arguments can't fit into locals in class file Functions/Color

I've also tried to remove the static modifier instead of just setting modifiers to public as such

 m.getMethod().setModifiers(m.getMethod().getModifiers() & ~Modifier.STATIC);

But the problem remains.

Is this actually possible?


Solution

  • So you are trying to remove a static modifier from a reserved entry point method name "main" in class Test. I think the compiler won't let you do that, because main is a reserved method name and can only have one predefined signature. And also, static methods are problematic; when called from within the class, if you remove the static modifier, all calls to them would also cause a compilation error, because they were not ment to be instance methods in original code.