[groovy-user] VerifyError when upgrading from Groovy 1.7.6 to 1.8.1

6 views
Skip to first unread message

Jason Griffith

unread,
Jul 25, 2011, 6:31:33 PM7/25/11
to us...@groovy.codehaus.org
Hello everyone!


We're trying to upgrade to Groovy 1.8.X.  First we were stuck by issue 4884 (http://jira.codehaus.org/browse/GROOVY-4884), but 1.8.1 fixed that, but now we've hit something else.

Our application runs on App Engine, using DataNucleus to enhance our persistent objects.  When we run the DataNucleus enhance step, we get this error:

java.lang.RuntimeException: Unexpected exception
        at com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:59)
        at com.google.appengine.tools.enhancer.Enhance.<init>(Enhance.java:60)
        at com.google.appengine.tools.enhancer.Enhance.main(Enhance.java:41)
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at com.google.appengine.tools.enhancer.Enhancer.execute(Enhancer.java:57)
        ... 2 more
Caused by: java.lang.VerifyError: (class: com/peersaver/model/TrackingTagReservation, method: hashCode signature: ()I) Expecting to find integer on stack
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
        at java.lang.Class.getDeclaredMethods(Class.java:1791)
        at org.datanucleus.metadata.annotations.AbstractAnnotationReader.getJavaBeanAccessorAnnotationsForClass(AbstractAnnotationReader.java:238)
        at org.datanucleus.metadata.annotations.AbstractAnnotationReader.getMetaDataForClass(AbstractAnnotationReader.java:128)
        at org.datanucleus.metadata.annotations.AnnotationManagerImpl.getMetaDataForClass(AnnotationManagerImpl.java:136)
        at org.datanucleus.metadata.MetaDataManager.loadAnnotationsForClass(MetaDataManager.java:2278)
        at org.datanucleus.metadata.MetaDataManager.loadClasses(MetaDataManager.java:385)
        at org.datanucleus.enhancer.DataNucleusEnhancer.getFileMetadataForInput(DataNucleusEnhancer.java:743)
        at org.datanucleus.enhancer.DataNucleusEnhancer.enhance(DataNucleusEnhancer.java:545)
        at org.datanucleus.enhancer.DataNucleusEnhancer.main(DataNucleusEnhancer.java:1252)
        ... 7 more


The class, TrackingTagReservation, has a hashCode method of:


@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (partnerItemId?.hashCode() ?: 0)
result = prime * result + (int) (_tagReservationDate ^ (_tagReservationDate >>> 32))
result = prime * result + (trackingTag?.hashCode() ?: 0)
result = prime * result + (userId?.hashCode() ?: 0)
return result;
}

_tagReservtionDate is a long primitive.  The others are Strings.

If I remove the line using _tagReservationDate, it enhances OK.   If it's in, Exceptionville.  

Any thoughts on why using the long would cause an error?

Thanks!
Jason

Jochen Theodorou

unread,
Jul 26, 2011, 5:15:11 AM7/26/11
to us...@groovy.codehaus.org
Am 26.07.2011 00:31, schrieb Jason Griffith:
> Hello everyone!
>
>
> We're trying to upgrade to Groovy 1.8.X. First we were stuck by issue
> 4884 (http://jira.codehaus.org/browse/GROOVY-4884), but 1.8.1 fixed
> that, but now we've hit something else.
>
> Our application runs on App Engine, using DataNucleus to enhance our
> persistent objects. When we run the DataNucleus enhance step, we get
> this error:
>
> java.lang.RuntimeException: Unexpected exception
[...]

> Caused by: java.lang.VerifyError: (class:
> com/peersaver/model/TrackingTagReservation, method: hashCode signature:
> ()I) Expecting to find integer on stack

that is one of the situations in which I really really hate those
meaningful messages from the JVM. We now know, something that should
have been an int, is not... oh well.

[...]


> The class, TrackingTagReservation, has a hashCode method of:
>
>
> @Override
> public int hashCode() {
> final int prime = 31;
> int result = 1;
> result = prime * result + (partnerItemId?.hashCode() ?: 0)
> result = prime * result + (int) (_tagReservationDate ^
> (_tagReservationDate >>> 32))
> result = prime * result + (trackingTag?.hashCode() ?: 0)
> result = prime * result + (userId?.hashCode() ?: 0)
> return result;
> }
>
> _tagReservtionDate is a long primitive. The others are Strings.
>
> If I remove the line using _tagReservationDate, it enhances OK. If it's
> in, Exceptionville.
>
> Any thoughts on why using the long would cause an error?

looking at the generated code from Groovy there is no problem according
to the asm check class adapter.

What you could do to help here is to compile the class one time normally
and do not enhance it, keeping the result, then one time with enhancing
and then checking both as well as comparing the two bytecodes. That may
lead to something...

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead
http://blackdragsview.blogspot.com/
For Groovy programming sources visit http://groovy.codehaus.org


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email


Jason Griffith

unread,
Jul 27, 2011, 5:50:49 PM7/27/11
to us...@groovy.codehaus.org
Hello Jochen,


Caused by: java.lang.VerifyError: (class:
com/peersaver/model/TrackingTagReservation, method: hashCode signature:
()I) Expecting to find integer on stack

that is one of the situations in which I really really hate those meaningful messages from the JVM. We now know, something that should have been an int, is not... oh well.

[...]
The class, TrackingTagReservation, has a hashCode method of:


@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (partnerItemId?.hashCode() ?: 0)
result = prime * result + (int) (_tagReservationDate ^
(_tagReservationDate >>> 32))
result = prime * result + (trackingTag?.hashCode() ?: 0)
result = prime * result + (userId?.hashCode() ?: 0)
return result;
}

_tagReservtionDate is a long primitive. The others are Strings.

If I remove the line using _tagReservationDate, it enhances OK. If it's
in, Exceptionville.

Any thoughts on why using the long would cause an error?

looking at the generated code from Groovy there is no problem according to the asm check class adapter.

What you could do to help here is to compile the class one time normally and do not enhance it, keeping the result, then one time with enhancing and then checking both as well as comparing the two bytecodes. That may lead to something...

Unfortunately, enhancement dies without writing anything, so I can't compare that way...  And it turns out that enhancement throwing Exceptions was only one way it could die.  I removed the enhancement step from our build, and when we moved on to building our src-test tree, this exception was thrown:

BUILD FAILED
/Users/jasong/Documents/workspace/main/build.xml:194: java.lang.VerifyError: (class: com/peersaver/model/TrackingTagReservation, method: hashCode signature: ()I) Expecting to find integer on stack
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
at java.lang.Class.getDeclaredFields(Class.java:1743)
at org.codehaus.groovy.vmplugin.v5.Java5.configureClassNode(Java5.java:321)
at org.codehaus.groovy.ast.ClassNode.lazyClassInit(ClassNode.java:264)
at org.codehaus.groovy.ast.ClassNode.getInterfaces(ClassNode.java:358)
[...]
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:280)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:109)

Looks like any use of the class causes a VerifyError.

But I was able to get the code to build and test by changing the hashCode method to:

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (partnerItemId?.hashCode() ?: 0)
Long workaround = new Long(_tagReservationDate)
result = prime * result + (int) (workaround ^ (workaround >>> 32))
result = prime * result + (trackingTag?.hashCode() ?: 0)
result = prime * result + (userId?.hashCode() ?: 0)
return result;
}

I've tried comparing the bytecodes of the passing and failing versions, but my bytecode-reading experience is a bit limited...  But one thing that pops out at me is the breaking .class file contains:

   L13
    ILOAD 3: prime
    ILOAD 5: result
    IMUL
    ALOAD 0: this
    GETFIELD TrackingTagReservation._tagReservationDate : long
    ALOAD 0: this
    GETFIELD TrackingTagReservation._tagReservationDate : long
    LDC 32
    I2L
    LUSHR
    LXOR
    INVOKESTATIC DefaultTypeTransformation.box(long) : Object
    CHECKCAST Long
    INVOKESTATIC DefaultTypeTransformation.intUnbox(Object) : int
    IADD
    ISTORE 9
    ILOAD 9
    ISTORE 5: result
    ILOAD 9
    POP
   L14

Are those two ALOAD/GETFIELD calls correct or are they duplicated?  The working .class file line that seems to correspond is:

   L14
    ILOAD 3: prime
    ILOAD 5: result
    IMUL
    ALOAD 1
    LDC 12
    AALOAD
    ALOAD 9: workaround
    ALOAD 1
    LDC 13
    AALOAD
    ALOAD 9: workaround
    LDC 32
    INVOKESTATIC DefaultTypeTransformation.box(int) : Object
    CHECKCAST Integer
    INVOKEINTERFACE CallSite.call(Object,Object) : Object
    INVOKEINTERFACE CallSite.call(Object,Object) : Object
    INVOKESTATIC DefaultTypeTransformation.intUnbox(Object) : int
    IADD
    ISTORE 11
    ILOAD 11
    ISTORE 5: result
    ILOAD 11
    POP
   L15

I'd love to help out more, but I'm not sure how. ;)  Please let me know!

Take care,
Jason

Jochen Theodorou

unread,
Jul 27, 2011, 6:47:00 PM7/27/11
to us...@groovy.codehaus.org
Am 27.07.2011 23:50, schrieb Jason Griffith:
[...]

> L13
> ILOAD 3: prime
> ILOAD 5: result
> IMUL
> ALOAD 0: this
> GETFIELD TrackingTagReservation._tagReservationDate : long
> ALOAD 0: this
> GETFIELD TrackingTagReservation._tagReservationDate : long
> LDC 32
> I2L
> LUSHR
> LXOR
> INVOKESTATIC DefaultTypeTransformation.box(long) : Object
> CHECKCAST Long
> INVOKESTATIC DefaultTypeTransformation.intUnbox(Object) : int
> IADD
> ISTORE 9
> ILOAD 9
> ISTORE 5: result
> ILOAD 9
> POP
> L14
>
> Are those two ALOAD/GETFIELD calls correct or are they duplicated?

this is different from what I have seen... anyway, let's have a look:
in [] the operandstack

> L13
> ILOAD 3: prime
> [int] ILOAD 5: result
> [int,int] IMUL
> [int] ALOAD 0: this
> [int, this] GETFIELD TrackingTagReservation._tagReservationDate : long
> [int, long] ALOAD 0: this
> [int, long, this] GETFIELD TrackingTagReservation._tagReservationDate : long
> [int, long, long] LDC 32
> [int, long, long, int] I2L
> [int, long, long, long] LUSHR

here is a problem, LUSHR expects [..., long, int], but we have 2 longs
here. The I2L should not have happened. So I can confirm a problem here.

Now the question is why I get a partially no optimized code... anyway,
not your problem. Can you please fill an issue for this? And can you
please attach an example I can compile to reproduce this?

Jay Ashworth

unread,
Jul 27, 2011, 8:19:00 PM7/27/11
to us...@groovy.codehaus.org
I don't know if this is the same root cause of the VerifyError, but after
upgrading to 1.8.0 to 1.8.1, one of our unit tests started to fail with that
response.

Here is a small sample application which duplicates it:
// Main.groovy
class Main {
static void main(String[] args) {
EvilClass evil = new EvilClass()
}
}

// EvilClass.groovy
class EvilClass {
String propertyName

String accessorMethodName() {
char[] characters = propertyName.toCharArray()
characters[0] = Character.toUpperCase(characters[0])
"get${new String(characters)}"
}
}

Trying to execute the main entry point in Main, will result in:

Exception in thread "main" java.lang.VerifyError: (class: EvilClass, method:
accessorMethodName signature: ()Ljava/lang/String;) Incompatible argument to
function
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at Main.class$(Main.groovy)
at Main.$get$$class$EvilClass(Main.groovy)
at Main.main(Main.groovy:9)


I've tried the same code with the 1.8.2 snapshot (27-Jul-11), and found that
no error occurs within it, so the underlying cause appears to already be
resolved.

If you still want a JIRA issue, I can enter one with my above sample,
although it may no longer be necessary to investigate; I suppose it depends
on whether this sample has any relevance to the problem that Jason is
having. My suggestion to you Jason, would be to try the 1.8.2 snapshot and
see if your VerifyError is resolved within it. If so, then a JIRA report
probably isn't necessary.

Note: I know about propertyName.capitalize(), and the unit test has been
changed to use it :)

--
View this message in context: http://groovy.329449.n5.nabble.com/VerifyError-when-upgrading-from-Groovy-1-7-6-to-1-8-1-tp4632721p4640769.html
Sent from the groovy - user mailing list archive at Nabble.com.

Jason Griffith

unread,
Jul 27, 2011, 9:45:33 PM7/27/11
to us...@groovy.codehaus.org
Unfortunately with today's (27-Jul-11) 1.8.2 snapshot the error still occurs.

Thanks for trying to save me some work, Jay, but looks like it's still a problem... ;) I'll put together a sample tomorrow and open an issue.

Cheers!
Jason

Reply all
Reply to author
Forward
0 new messages