java.lang.VerifyError 使用 Javassist 创建方法时抛出
java.lang.VerifyError thrown when creating a method using JavaAssist
我正在尝试使用 JavaAssist 版本 3.12。1.GA 为使用 Java 8 实现接口的 Pojo 生成一些运行时代码。我 运行尝试创建具有 return 类型对象的方法时出错。
错误:
Caused by: java.lang.VerifyError: (class: person, method: getColumnByIndex signature: (I)Ljava/lang/Object;) Wrong return type in function
添加 getColumnByIndex
方法时抛出。
这里是完整的例子class:
public class Example {
public interface Domain {
public int getIdentifier();
public Object getColumnByIndex(int i);
}
public static void main(final String[] args) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException {
final ClassPool pool = ClassPool.getDefault();
final CtClass cc = pool.makeClass("Person");
cc.addInterface(resolveCtClass(Domain.class));
final CtField idField = new CtField(CtClass.intType, "id", cc);
final CtMethod idGetter = CtNewMethod.getter("getId", idField);
final CtMethod idSetter = CtNewMethod.setter("setId", idField);
cc.addField(idField);
cc.addMethod(idGetter);
cc.addMethod(idSetter);
final CtField firstNameField = new CtField(resolveCtClass(String.class), "firstName", cc);
final CtMethod firstNameGetter = CtNewMethod.getter("getFirstName", firstNameField);
final CtMethod firstNameSetter = CtNewMethod.setter("setFirstName", firstNameField);
cc.addField(firstNameField);
cc.addMethod(firstNameSetter);
cc.addMethod(firstNameGetter);
final CtMethod getIdentifier = CtNewMethod.make("public int getIdentifier () { return id; }", cc);
cc.addMethod(getIdentifier);
final CtMethod getColumnByIndex = CtNewMethod.make(
"public Object getColumnByIndex(int i) {"
+ "switch (i) {"
+ "case 0:"
+ "return id;"
+ "case 1:"
+ "return firstName;"
+ "default: "
+ "throw new IllegalArgumentException(\"Tried getting column index i, but this column index does not exist\");"
+ "}"
+ "}", cc);
cc.addMethod(getColumnByIndex);
final Class<?> dynamicClass = cc.toClass();
final Domain domainImpl = (Domain) dynamicClass.newInstance();
System.out.println(domainImpl.getIdentifier());
System.out.println(domainImpl.getColumnByIndex(0));
}
private static CtClass resolveCtClass(final Class<?> clazz) throws NotFoundException {
final ClassPool pool = ClassPool.getDefault();
return pool.get(clazz.getName());
}
如何解决 java.lang.VeryifyError?
显然,int
类型的 id
字段不会自动装箱到 Integer
中,因此您要么手动完成:
switch (i) {
case 0: return Integer.valueOf(id);
case 1: return firstName;
default: throw new IllegalArgumentException("...");
}
或者您将所有内容都转换为 Integer
,包括 Domain.getIdentifier()
的 return 类型。 Java 中的基本类型不是 Object
的!包装类型的存在是为了在 JVM 中伪造一个单一的根层次结构,编译器会在适当的时候悄悄地插入像 Integer.valueOf(int)
和 Integer.intValue()
这样的调用,但有时抽象会泄露给用户。
由于您正在编写的代码似乎是一个数据库访问的东西,我更喜欢第二个选项,这样一切都可以为空 - 否则代表一个尚未插入的记录你必须依赖一些金丝雀值,如零、-1 或其他。
可运行gist
我正在尝试使用 JavaAssist 版本 3.12。1.GA 为使用 Java 8 实现接口的 Pojo 生成一些运行时代码。我 运行尝试创建具有 return 类型对象的方法时出错。
错误:
Caused by: java.lang.VerifyError: (class: person, method: getColumnByIndex signature: (I)Ljava/lang/Object;) Wrong return type in function
添加 getColumnByIndex
方法时抛出。
这里是完整的例子class:
public class Example {
public interface Domain {
public int getIdentifier();
public Object getColumnByIndex(int i);
}
public static void main(final String[] args) throws NotFoundException, CannotCompileException, InstantiationException, IllegalAccessException {
final ClassPool pool = ClassPool.getDefault();
final CtClass cc = pool.makeClass("Person");
cc.addInterface(resolveCtClass(Domain.class));
final CtField idField = new CtField(CtClass.intType, "id", cc);
final CtMethod idGetter = CtNewMethod.getter("getId", idField);
final CtMethod idSetter = CtNewMethod.setter("setId", idField);
cc.addField(idField);
cc.addMethod(idGetter);
cc.addMethod(idSetter);
final CtField firstNameField = new CtField(resolveCtClass(String.class), "firstName", cc);
final CtMethod firstNameGetter = CtNewMethod.getter("getFirstName", firstNameField);
final CtMethod firstNameSetter = CtNewMethod.setter("setFirstName", firstNameField);
cc.addField(firstNameField);
cc.addMethod(firstNameSetter);
cc.addMethod(firstNameGetter);
final CtMethod getIdentifier = CtNewMethod.make("public int getIdentifier () { return id; }", cc);
cc.addMethod(getIdentifier);
final CtMethod getColumnByIndex = CtNewMethod.make(
"public Object getColumnByIndex(int i) {"
+ "switch (i) {"
+ "case 0:"
+ "return id;"
+ "case 1:"
+ "return firstName;"
+ "default: "
+ "throw new IllegalArgumentException(\"Tried getting column index i, but this column index does not exist\");"
+ "}"
+ "}", cc);
cc.addMethod(getColumnByIndex);
final Class<?> dynamicClass = cc.toClass();
final Domain domainImpl = (Domain) dynamicClass.newInstance();
System.out.println(domainImpl.getIdentifier());
System.out.println(domainImpl.getColumnByIndex(0));
}
private static CtClass resolveCtClass(final Class<?> clazz) throws NotFoundException {
final ClassPool pool = ClassPool.getDefault();
return pool.get(clazz.getName());
}
如何解决 java.lang.VeryifyError?
显然,int
类型的 id
字段不会自动装箱到 Integer
中,因此您要么手动完成:
switch (i) {
case 0: return Integer.valueOf(id);
case 1: return firstName;
default: throw new IllegalArgumentException("...");
}
或者您将所有内容都转换为 Integer
,包括 Domain.getIdentifier()
的 return 类型。 Java 中的基本类型不是 Object
的!包装类型的存在是为了在 JVM 中伪造一个单一的根层次结构,编译器会在适当的时候悄悄地插入像 Integer.valueOf(int)
和 Integer.intValue()
这样的调用,但有时抽象会泄露给用户。
由于您正在编写的代码似乎是一个数据库访问的东西,我更喜欢第二个选项,这样一切都可以为空 - 否则代表一个尚未插入的记录你必须依赖一些金丝雀值,如零、-1 或其他。
可运行gist