Friday 1 May 2020

Javassist: Dealing with Frozen classes

When a CtClass object is converted into a class file by writeFile(), toClass(), or toBytecode(), Javassist freezes that CtClass object. Further modifications on CtClass objects are not allowed.

App.java
package com.sample.app;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class App {

 public static void main(String args[]) throws Exception {
  ClassPool pool = ClassPool.getDefault();

  CtClass ctClass = pool.makeClass("com.sample.app.Arithmetic");

  CtMethod sum = new CtMethod(CtClass.intType, "sum", new CtClass[] { CtClass.intType, CtClass.intType },
    ctClass);
  sum.setBody("return $1 + $2;");

  ctClass.addMethod(sum);

  ctClass.writeFile("/Users/Shared/assistDemos");
  
  CtMethod areaOfCircle = new CtMethod(CtClass.doubleType, "areaOfCircle", new CtClass[] { CtClass.doubleType },
    ctClass);
  areaOfCircle.setBody("return 3.14 + $1;");

  ctClass.addMethod(areaOfCircle);

  ctClass.writeFile("/Users/Shared/assistDemos");
  

 }
}

When you ran above program, you will end up with below exception.

Exception in thread "main" java.lang.RuntimeException: com.sample.app.Arithmetic class is frozen
         at javassist.CtClassType.checkModify(CtClassType.java:321)
         at javassist.CtBehavior.setModifiers(CtBehavior.java:178)
         at javassist.CtMethod.<init>(CtMethod.java:67)
         at com.sample.app.App.main(App.java:22)

How to modify a frozen class?
A frozen CtClass can be defrost so that modifications of the class definition will be permitted.

Example
// Defrosting
ctClass.defrost();

App.java
package com.sample.app;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class App {

 public static void main(String args[]) throws Exception {
  ClassPool pool = ClassPool.getDefault();

  CtClass ctClass = pool.makeClass("com.sample.app.Arithmetic");

  CtMethod sum = new CtMethod(CtClass.intType, "sum", new CtClass[] { CtClass.intType, CtClass.intType },
    ctClass);
  sum.setBody("return $1 + $2;");

  ctClass.addMethod(sum);

  ctClass.writeFile("/Users/Shared/assistDemos");
  
  // Defrosting
  ctClass.defrost();
  
  CtMethod areaOfCircle = new CtMethod(CtClass.doubleType, "areaOfCircle", new CtClass[] { CtClass.doubleType },
    ctClass);
  areaOfCircle.setBody("return 3.14 + $1;");

  ctClass.addMethod(areaOfCircle);

  ctClass.writeFile("/Users/Shared/assistDemos");
  

 }
}

You can observe Arithmetic.class file is generated at folder /Users/Shared/assistDemos.

$tree /Users/Shared/assistDemos
/Users/Shared/assistDemos
└── com
    └── sample
        └── app
            └── Arithmetic.class

3 directories, 1 file

Open Arithemtic.class in decompiler to see the source code.

Previous                                                    Next                                                    Home

No comments:

Post a Comment