Removing final modifier of inner classes
mburger Oct 1, 2007 11:27 AMHello!
I've written a tool that removes the final modifier from class files. That works perfectly with "outer" classes, but with inner classes javassist seems to fail. Here is a small test case.
The class FinalRemover does the job:
package test;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.Modifier;
public class FinalRemover {
public static void main(String[] args) throws Exception {
process("test.NoInner");
process("test.WithInner");
process("test.WithInner$NotStatic");
process("test.WithInner$Static");
}
public static void process(String className) throws Exception {
System.out.println("Processing class: " + className);
ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get(className);
removeFinal(cc);
if (Modifier.isFinal(cc.getModifiers())) {
throw new IllegalStateException("Class '" + className + "' is not final?!?");
}
cc.writeFile("/tmp/test_patched/patched");
System.out.println("Class was written: " + className);
System.out.println();
}
protected static void removeFinal(CtClass clazz) {
int modifiers = clazz.getModifiers();
if (Modifier.isFinal(modifiers)) {
System.out.println("Removing final modifier: " + clazz.getName());
int notFinalModifier = Modifier.clear(modifiers, Modifier.FINAL);
clazz.setModifiers(notFinalModifier);
}
}
}
The class NoInner has no inner class:
package test;
public final class NoInner {
}
Finally, the class WithInner has two inner classes:
package test;
public class WithInner {
public WithInner() {
super();
}
public static final class Static {
public static final String CONST = "Static inner class";
}
public final class NotStatic {
public static final String CONST = "Not static inner class";
}
}
Running the tool writes the following output:
Processing class: test.NoInner Removing final modifier: test.NoInner Class was written: test.NoInner Processing class: test.WithInner Class was written: test.WithInner Processing class: test.WithInner$NotStatic Removing final modifier: test.WithInner$NotStatic Class was written: test.WithInner$NotStatic Processing class: test.WithInner$Static Removing final modifier: test.WithInner$Static Class was written: test.WithInner$Static
I decompiled the written class files using JAD. A diff between the original and the patched class NoInner shows the expected result:
$ diff orig/NoInner.jad patched/NoInner.jad 9c9 < public final class NoInner --- > public class NoInner
But, between the original and the patched class WithInner, there is no difference:
$ diff orig/WithInner.jad patched/WithInner.jad
Thus, the final modifier was not removed from the byte code. Please note the IllegalStateException in my code: javassist thinks that modifier was removed, but it is still contained in the byte code written the the file.
Any ideas?
Regards
Martin