[jboss-user] [Javassist user questions] - Removing final modifier of inner classes

mburger do-not-reply at jboss.com
Mon Oct 1 11:27:48 EDT 2007


Hello!

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

View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4090308#4090308

Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4090308



More information about the jboss-user mailing list