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