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.