繁体   English   中英

使用JavaAssist创建方法时抛出java.lang.VerifyError

[英]java.lang.VerifyError thrown when creating a method using JavaAssist

我试图使用JavaAssist版本3.12.1.GA来执行使用Java 8实现接口的Pojo的某些运行时代码生成。尝试创建具有Object返回类型的方法时遇到错误。

错误:

Caused by: java.lang.VerifyError: (class: person, method: getColumnByIndex signature: (I)Ljava/lang/Object;) Wrong return type in function

添加getColumnByIndex方法时被抛出。

这是完整的示例类:

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()的返回类型。 Java中的原始类型不是Object的! 存在包装程序类型以伪造JVM中的单个根层次结构,并且编译器在适当时静默插入诸如Integer.valueOf(int)Integer.intValue()类的调用,但是有时抽象泄漏给用户。

由于您正在编写的代码似乎是数据库访问的东西,因此,我宁愿使用第二种选择,以便所有内容都可以为空-否则,要表示要插入的记录,您将不得不依赖一些零进制值(如零) ,-1或其他值。

可运行的要点

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM