javadynamicclassloaderjava-assist

Javassist - Numeric operations in CtMethod method body throws java.lang.VerifyError


Please see below code of creating a class and method using javassist:

public Class generateClass(String className, String methodName)
            throws CannotCompileException, NotFoundException {
   ClassPool pool = ClassPool.getDefault();
   CtClass cc = pool.makeClass(className);

   ClassLoader classLoader = FormulaAPI.class.getClassLoader();
   pool.appendClassPath(new LoaderClassPath(classLoader));
   pool.importPackage("com.formula");

   String methodBody = "return ($w)($1.evaluate(\"L\") + 25.0);";

   CtClass apiClass = pool.get("com.formula.FormulaAPI");

   CtClass doubleWrapperClass = pool.get("java.lang.Double");

   CtMethod m = new CtMethod(doubleWrapperClass,methodName,new CtClass[]{apiClass},cc);
   m.setBody(methodBody);
   cc.addMethod(m);

   return cc.toClass();
}

After calling this method, I get the error:

Exception in thread "main" java.lang.VerifyError: (class: Formulae, method: formula1 signature: (Lcom/formulabuilder/FormulaAPI;)Ljava/lang/Double;) Wrong return type in function

Does Javassist not support numeric operations in method body? I am trying to call a method and add a number to it before it returns the value as below:

String methodBody = "return ($w)($1.evaluate(\"L\") + 25.0);";

How can I achieve numeric operations like +, *, /, <, <= etc. in method body?


Solution

  • The problem is most likely that javassist doesnt support autoboxing. So java.lang.Double is not compatible with double. Numeric operators are only available for primitive types.

    So if you want to keep the signatures, you need to box/unbox the objects/primitives yourself.

    Something like

    String methodBody = "return java.lang.Double.valueOf($1.evaluate(\"L\").doubleValue() + 25.0d);";
    

    (you might want to add null handling if evaluate() can return null)