-
Notifications
You must be signed in to change notification settings - Fork 227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Crash with "VerifyError: Expecting a stackmap frame" when loading Android classes #25
Comments
Could a constructor be the cause? |
What exactly about the constructor? As far as I can see, the super class has one zero args constructor. Source is not visible, because the code is proprietary. |
I meant that lambda is declared at initialization. But checked that and can't confirm that. |
Now I understand. Yeah, it crashes no matter where the lambda is defined. I originally had it inside a method but put it in the class body to make the example shorter. |
I'm unable to build your example project:
Also where can I get the SupportMapFragment.class file? Please attach your file or give an URL to the exactly same version. From the error message it sounds like it's not a fully valid Java class file. |
I noticed that the build mentions ProGuard, in which case it could be related to this: http://stackoverflow.com/questions/19928927/obfuscation-causes-verifyerror-expecting-a-stackmap-frame Try removing Retrolamdba and ProGuard one-by-one from the project and see whether it's possible to execute the file under Java 8. |
Building without ProGuard still doesn't work. I uploaded a complete project you should be able to (not) compile: https://github.com/cypressious/RetrolambdaFailure |
Thanks, I'm now getting the same crash. I've only managed to figure out that the I'm getting the same crash also when running that class on Java 8 without Retrolamdba, i.e.
Even just this is enough to reproduce the issue:
|
I can think of three solutions of which only one is realistic:
[1] It seems intentional, because the bytecode spec says in §4.7.4 "In a class file whose version number is greater than or equal to 50.0, if a method's Code attribute does not have a StackMapTable attribute, it has an implicit stack map attribute." Version 50.0 means Java 6, so it seems that according to the spec stack map frames have been required since Java 6, but the JVM has been checking them only since Java 7. But in Java 7 release notes it says "Classfiles with version number 51 are exclusively verified using the type-checking verifier, and thus the methods must have StackMapTable attributes when appropriate. For classfiles with version 50, the Hotspot JVM would (and continues to) failover to the type-inferencing verifier if the stackmaps in the file were missing or incorrect. This failover behavior does not occur for classfiles with version 51 (the default version for Java SE 7). Any tool that modifies bytecode in a version 51 classfile must be sure to update the stackmap information to be consistent with the bytecode in order to pass verification." Did they suddenly make Java 8 even stricter about that? |
Crap. To answer my rethorical question in the previous comment, this it what it reads in the JVM spec §4.10.1. Verification by Type Checking, the relevant words highlighted by me:
Seems that Java 8 was the limit. |
Actually I had a fourth idea of a workaround: Use Retrolambda's Java agent to add stack map frames to all classes with bytecode version 50.0. It needs to be done only at runtime inside Java 8 VM - the updated classes don't need to be saved. |
I'll try to go for the workaround number 4. It's safer than using the Some help with this would let me do it faster: http://stackoverflow.com/questions/24927993/what-kind-of-java-code-requires-stackmap-frames |
Sadly I know nothing about this kind of stuff, but I upvoted your question. |
Phew, finally found out the reason. Version 5.0.77 of play-services is marked to be Java 7 bytecode (version 51.0), but it's missing the stackmap frames. In other words the bytecode is broken and must be rejected by every JVM that conforms to the spec. Version 4.4.52 of play-services contains Java 6 bytecode (version 50.0) and even though it's missing the stackmap frames, that may be allowed by JVMs. The example project can be fixed by specifying the version to use:
So this is a bug in play-services and it should be fixed there. As a temporary workaround it might be good to allow configuring custom JVM options in gradle-retrolambda so that users may add the |
Great to hear that! 👍 |
Requires Android SDK at ANDROID_HOME. The version used was android-studio-bundle-135.1245622-windows. Contains lots of hacks in getting the tests to compile in Maven.
@orfjackal is there a way to run with |
@vinc3m1 gradle-retrolambda has been updated to support this, check the README for details. |
@orfjackal +1 Thanks for the |
I'm using the gradle plugin which can be found here and I'm getting the following crash during compilation:
It seems that any class that extends Google's
SupportMapFragment
from the Google Play Services and uses any lambdas will produce this crash.Here's a minimal app that produces the crash: https://gist.github.com/cypressious/5ccfe84a31fd836fe125
The text was updated successfully, but these errors were encountered: