在 Javassist 中,如何在使用 CtMethod 创建动态方法时将 return 类型的方法设置为 java.lang.Double
In Javassist, how to set return type of method to java.lang.Double when creating dynamic method using CtMethod
我必须在 运行 时动态创建 class 和方法。为此,我正在使用 Javassist:
我要动态创建的方法是:
public Double formula1(FormulaAPI api) {
return api.evaluate(\"L\");
}
如果我使用 CtMethod.make(..)
将上述整个方法作为方法体传递,它工作正常。
但我想让它更通用,即我只想将 return api.evaluate(\"L\");
作为我的方法主体,并想使用 JavaAssist API 方法来设置名称,return 类型等
尝试这样做时,出现错误:
***Exception in thread "main" java.lang.VerifyError:
(class: Formulae, method: formula1 signature: (Lcom/formula/FormulaAPI;)D) Wrong return type in function***
我的问题是:调用时:
CtMethod m = new CtMethod(...);
如何将 CtMethod 的 return 类型设置为 java.lang.Double 而不是 CtPrimitiveType.doubleType ?
我的全部源代码是:
public class JavaAssistTest {
private static final String className = "Formulae";
private static final String methodName = "formula1";
public static void main(String[] args) throws Exception{
JavaAssistTest jj = new JavaAssistTest();
try {
Class clazz = jj.generateClass(className, methodName);
Object obj = clazz.newInstance();
Method method = clazz.getDeclaredMethod(methodName,FormulaAPI.class);
FormulaAPI api = new FormulaAPI();
method.invoke(obj,api);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
}
}
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 .evaluate(\"L\");";
CtClass apiClass = pool.get("com.formula.FormulaAPI");
CtMethod m = new CtMethod(CtPrimitiveType.doubleType,methodName,new CtClass[]{apiClass},cc);
m.setBody(methodBody);
cc.addMethod(m);
return cc.toClass();
}
}
公式API class如下:
public class FormulaAPI {
public Double evaluate(String source){
System.out.println("printing in FormulaAPI ");
return 2.0;
}
}
显然 CtPrimitiveType.doubleType
不是要使用的 CtClass 类型,因为您需要包装器 class 而不是,这就是您获得异常的原因。
但解决方案非常简单,您只需将 Double 类型作为 CtClass 并使用它即可。所以修改你的生成方法看起来像:
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 .evaluate(\"L\");";
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();
}
运行你的代码经过这些修改,你应该没有例外。
我必须在 运行 时动态创建 class 和方法。为此,我正在使用 Javassist:
我要动态创建的方法是:
public Double formula1(FormulaAPI api) {
return api.evaluate(\"L\");
}
如果我使用 CtMethod.make(..)
将上述整个方法作为方法体传递,它工作正常。
但我想让它更通用,即我只想将 return api.evaluate(\"L\");
作为我的方法主体,并想使用 JavaAssist API 方法来设置名称,return 类型等
尝试这样做时,出现错误:
***Exception in thread "main" java.lang.VerifyError:
(class: Formulae, method: formula1 signature: (Lcom/formula/FormulaAPI;)D) Wrong return type in function***
我的问题是:调用时: CtMethod m = new CtMethod(...); 如何将 CtMethod 的 return 类型设置为 java.lang.Double 而不是 CtPrimitiveType.doubleType ?
我的全部源代码是:
public class JavaAssistTest {
private static final String className = "Formulae";
private static final String methodName = "formula1";
public static void main(String[] args) throws Exception{
JavaAssistTest jj = new JavaAssistTest();
try {
Class clazz = jj.generateClass(className, methodName);
Object obj = clazz.newInstance();
Method method = clazz.getDeclaredMethod(methodName,FormulaAPI.class);
FormulaAPI api = new FormulaAPI();
method.invoke(obj,api);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
}
}
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 .evaluate(\"L\");";
CtClass apiClass = pool.get("com.formula.FormulaAPI");
CtMethod m = new CtMethod(CtPrimitiveType.doubleType,methodName,new CtClass[]{apiClass},cc);
m.setBody(methodBody);
cc.addMethod(m);
return cc.toClass();
}
}
公式API class如下:
public class FormulaAPI {
public Double evaluate(String source){
System.out.println("printing in FormulaAPI ");
return 2.0;
}
}
显然 CtPrimitiveType.doubleType
不是要使用的 CtClass 类型,因为您需要包装器 class 而不是,这就是您获得异常的原因。
但解决方案非常简单,您只需将 Double 类型作为 CtClass 并使用它即可。所以修改你的生成方法看起来像:
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 .evaluate(\"L\");";
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();
}
运行你的代码经过这些修改,你应该没有例外。