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.