Status fields:
creation_ts: | 2009-03-23 22:24 |
---|---|
component: | verifier |
version: | unspecified |
rep_platform: | All |
op_sys: | All |
bug_status: | RESOLVED |
resolution: | FIXED |
reporter: | michi@complang.tuwien.ac.at |
It seems we have some problems with the Javassist library which is used quite often (by Hibernate or Tapestry for example). It generates bytecode at runtime and loads it. The generated bytecode is different to what we are used to load and (maybe) triggers some hidden bugs. I'll have to analyze this further. This is the exception Cacao is generating: Exception in thread "main" java.lang.ClassFormatError: Foo (Arguments can't fit into locals) at java.lang.VMClassLoader.defineClass(Native Method) at java.lang.VMClassLoader.defineClassWithTransformers(VMClassLoader.java:454) at java.lang.ClassLoader.defineClass(ClassLoader.java:471) at java.lang.ClassLoader.defineClass(ClassLoader.java:436) at LoadBytes.load(LoadBytes.java:43) at LoadBytes.main(LoadBytes.java:53)
I have written a testcase to trigger the problem. Once the check in our loader is removed we get a verification error explaining what the real problem is. This is the exception I am talking about: java.lang.VerifyError: (class: Foo, method: <clinit> signature: ()V) Not enough local variables for method arguments at java.lang.reflect.VMField.getInt(Native Method) at java.lang.reflect.Field.getInt(Field.java:374) at PR125.test(PR125.java:36) The problem is the class initializer <clinit> which should be marked ACC_STATIC but isn't. It therefore receives at least one argument (the this reference) which needs at least one local variable. But the max_locals for the method is set to 0 which leads to the verification error above. The strange thing is that HotSpot not only loads the bytecode, but also successfully calls the buggy <clinit> method as class initializer. Funny thing, a "non-static class initilaizer". This is the testcase I was talking about: http://mips.complang.tuwien.ac.at/hg/cacao/rev/c657cc463135
I have resolved the problem by looking at the VM spec (section 4.6) which states that all (except ACC_STRICT) access flags need to be ignored for class initializers. Ignoring them also means setting the ACC_STATIC flag (section 3.9) per default. I really wonder about this stuff sometimes. This is the fixing changeset: http://mips.complang.tuwien.ac.at/hg/cacao/rev/347c73da29cf This is what the VM spec says: http://java.sun.com/docs/books/jvms/second_edition/html/ClassFile.doc.html#1513 PS: Remember that you need the second edition of the VM spec. Don't even look at your first edition hardcopy like I did.