VerifyError when instanciating a generated class (Bad type i
kromate Apr 2, 2009 5:04 AMDear 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.
 
    