5 Replies Latest reply on Apr 3, 2009 8:48 AM by jaikiran

    VerifyError when instanciating a generated class (Bad type i

      Dear all,

      I'm using javassist to generate access class for reflection, following this tutorial:
      http://www.ibm.com/developerworks/java/library/j-dyn0610/index.html?S_TACT=105AGX02&S_CMP=EDU

      Everything works fine with my version, but it is not working with field without getter/setter. I need my generated access class to be able to access field directly in some case.

      So I wrote the following piece of code:

      ....
      protected static byte[] createAccess(final Class targetJavaClass, final String field, final String generatedClassName)
       throws Exception {
      
      //... code to get read/write method
      
       String targetName = targetJavaClass.getName();
       ClassPool pool = ClassPool.getDefault();
       CtClass accessClass = pool.makeClass(generatedClassName);
       CtClass targetClass = pool.get(targetName);
       final CtClass ctFieldClass = pool.get("java.lang.Object");
       final CtClass[] ctFieldClassParam = new CtClass[]{ctFieldClass};
       CtMethod meth;
      
       // add target object field to class
       accessClass.addField(new CtField(targetClass, "target", accessClass));
      
       // add public default constructor method to class
       CtConstructor cons = new CtConstructor(CT_NO_ARGS, accessClass);
       cons.setBody(";");
       accessClass.addConstructor(cons);
      
       // add public <code>setTarget</code> method
       meth = new CtMethod(CtClass.voidType, "setTarget", ctFieldClassParam, accessClass);
       meth.setBody("target = (" + targetJavaClass.getName() + ") $1;");
       accessClass.addMethod(meth);
      
      
       String src;
      
       // add public <code>setValue</code> method
       meth = new CtMethod(CtClass.voidType, "setValue", ctFieldClassParam, accessClass);
       final Class<?> fieldType = writer.getParameterTypes()[0];
       String cast$1 = "(" + fieldType.getName() + ") $1";
       if(directWriteField) src = "target." + field + " = " + " $1;";
       else src = "target." + writer.getName() + "(" + cast$1 + ");";
       meth.setBody(src);
       accessClass.addMethod(meth);
      
       // add public <code>getValue</code> method
       meth = new CtMethod(ctFieldClass, "getValue", CT_NO_ARGS, accessClass);
       if(directReadField) src = field;
       else src = reader.getName() + "()";
       meth.setBody("return (java.lang.Object) target." + src + ";");
       accessClass.addMethod(meth);
      
       // return binary representation of completed class
       accessClass.addInterface(pool.get(IAccess.class.getName()));
       accessClass.writeFile();
       return accessClass.toBytecode();
       }
      ...
      


      Execution of this code throws an exception after class generation, when calling newInstance on it:
      java.lang.VerifyError: (class: Accessor$com/bnpparibas/eqd/fish/fwk/introspection/TestCachedIntrospectionInfo$SampleBean_secret, method: setValue signature: (Ljava/lang/Object;)V) Bad type in
      putfield/putstatic
      at java.lang.Class.getDeclaredConstructors0(Native Method)
       at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357)
       at java.lang.Class.getConstructor0(Class.java:2671)
       at java.lang.Class.newInstance0(Class.java:321)
       at java.lang.Class.newInstance(Class.java:303)
      


      The part of the code responsible of this is the following part of code:
      f(directWriteField) src = "target." + field + " = " + " $1;";
      


      If I remove this line, there are no error.

      Here is the decompiled code of the faulty generated class:
      package Accessor$com.bnpparibas.eqd.fish.fwk.introspection;
      
      import com.bnpparibas.eqd.fish.fwk.introspection.IAccess;
      import com.bnpparibas.eqd.fish.fwk.introspection.SampleBean;
      
      public class SampleBean_directAccessField
       implements IAccess {
      
       SampleBean target = null;
      
       public SampleBean_directAccessField() {
       }
      
       public void setTarget(Object obj) {
       target = (SampleBean)obj;
       }
      
       public void setValue(Object obj) {
       target.directAccessField = ((java.util.Date) (obj));
       }
      
       public Object getValue() {
       return (Object)target.directAccessField;
       }
      }
      


      And the directAccesField of the target object is a java.util.Date.

      I've spend to much time on this problem and I can't figure what the problem is.

      Thanks for any help you can provide.

      Regards.
      K.



        • 1. Re: VerifyError when instanciating a generated class (Bad ty
          jaikiran

           

          public class SampleBean_directAccessField
          implements IAccess {

          SampleBean target = null;


          public void setValue(Object obj) {
          target.directAccessField = ((java.util.Date) (obj));
          }


          Is the "directAccessField" in SampleBean a public field? If it's not, then it won't be accessible.

          • 2. Re: VerifyError when instanciating a generated class (Bad ty

            Yes this is a public field.

            In this case the error will much be something like an IllegalAccessException.

            It's like there is a type problem.

            The strange thing is that this line is not working:

            if(directWriteField) src = "target." + field + " = " + " $1;";


            but this one is:
            if(directWriteField) src = "target." + field + " = new java.util.Date();";


            • 3. Re: VerifyError when instanciating a generated class (Bad ty

              The last line of my previous post is not easy to read. It is:
              if(directWriteField) src = "target." + field + " = new java.util.Date();";

              • 4. Re: VerifyError when instanciating a generated class (Bad ty

                By the way I re-post the error I get with this code. The one I've posted is was not matching.

                Caused by: java.lang.VerifyError: (class: Accessor$com/bnpparibas/eqd/fish/fwk/introspection/SampleBean_directAccessField, method: setValue signature: (Ljava/lang/Object;)V) Bad type in putfield/putstatic
                 at java.lang.Class.getDeclaredConstructors0(Native Method)
                 at java.lang.Class.privateGetDeclaredConstructors(Class.java:2357)
                 at java.lang.Class.getConstructor0(Class.java:2671)
                 at java.lang.Class.newInstance0(Class.java:321)
                 at java.lang.Class.newInstance(Class.java:303)


                (out of topic) his there an edit post tool ? I've looked for one, but I did not see any.

                Thanks.



                • 5. Re: VerifyError when instanciating a generated class (Bad ty
                  jaikiran

                  Looking at this code:


                  String cast$1 = "(" + fieldType.getName() + ") $1";
                  if(directWriteField) src = "target." + field + " = " + " $1;";


                  I think you have a typo. You should be having this:

                  String cast$1 = "(" + fieldType.getName() + ") $1";
                   if(directWriteField) src = "target." + field + " = " + cast$1 + ";";
                  


                  (out of topic) his there an edit post tool ?


                  No, there's no edit option.