Community
Participate
Working Groups
Build Identifier: 20110916-0149 Java version: JVM build 1.7.0_01-b08 Compiler: 1.7 compliance Class to reproduce: public class VerifyErrorTest { public static void main(String[] args) { testError(3, 4, "d"); testNoError(3, 4, "d"); } public static void testError(Number n0, Number n1, String refValue) { Number result = refValue.equals("ttt") ? n0 : (n1 == null ? null : n1.intValue()); } public static void testNoError(Number n0, Number n1, String refValue) { Number result = null; if (refValue.equals("ttt")) { result = (Integer) n0; } else { if (n1 == null) { result = null; } else { result = n1.intValue(); } } } } Result: Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 28 in method VerifyErrorTest.testError(Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/String;)V at offset 10 at java.lang.Class.getDeclaredMethods0(Native Method) at java.lang.Class.privateGetDeclaredMethods(Class.java:2442) at java.lang.Class.getMethod0(Class.java:2685) at java.lang.Class.getMethod(Class.java:1620) at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:484) at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:476) Notes: - The method testNoError does not generate this error (workaround). - This issue may be related to bug 361053 (no way of testing with the HEAD code) Reproducible: Always Steps to Reproduce: 1. Create a new java project (java 1.7 compliance). 2. Add the provided class 3. Run
Reproduced on HEAD, will follow up for 3.8 M4 and once fix is identified will consider for 3.7.2 also.
If you're stuck, please use the VM argument -XX:-UseSplitVerifier to run the program. I confirm that there is no verify error with this option.
Created attachment 206344 [details] Proposed fix + regression test The problem comes from the creation of StackDepthMarker entries at the same location for each conditional expression. The outer one was not recorded and therefore the type on the stack was java.lang.Integer instead of java.lang.Number. Let me know if you have issues to apply the patch.
(In reply to comment #3) > Let me know if you have issues to apply the patch. Thanks for the patch, Olivier. I plan to first review the relevant chapter of the JVM spec and familiarize myself with the architecture of this verification scheme, After that I'll study the patch and take it forward. (Fortunately the latest edition of the JVM spec for JDK7 documents the stack map table structure unlike earlier editions where this went unspecified.)
We have this problem with our (quite big) code base. Because of our automated build (javac) and our Eclipse install, we have no choice but to force compiler version to 1.7 until this gets resolved. We hope this gets fixed in 3.7.2, and that we won't have to wait for too long for this service release.
(In reply to comment #5) > We have this problem with our (quite big) code base. Because of our automated > build (javac) and our Eclipse install, we have no choice but to force compiler > version to 1.7 until this gets resolved. We hope this gets fixed in 3.7.2, and > that we won't have to wait for too long for this service release. Sorry for the delay on this item. I was busy with a bunch of other issues. I can now take this up in earnest, study the documentation and the patch and take it forward. Our plan is to include a fix for this for 3.7.2 since this is a regression introduced at 3.7.1 time. 3.6.2 + JRE7 or 3.7 + JRE7 work alright. Will also need to check on 3.6.2+Java7.
Minimal test case that works well with 3.7 and fails to verify with 3.8 top of branch: public class X { public static void main(String[] args) { Object o = args != null ? args : (args == null ? null : args.length); } }
(In reply to comment #6) > (In reply to comment #5) > 3.6.2 + JRE7 or 3.7 + JRE7 work alright. Keep tripping on this: The bug is long standing, but it manifests only now as a VM is allowed to fall back on earlier verification strategies when verifying class files generated for JDK6 (major version 50), while JDK7 vm is not allowed to fall back when working with a class file generated for JDK7 (major version 51). So there is no material difference in the class file produced by eclipse 3.7 and 3.7.1 or 3.8 M3, but there will be a user visible symptom (verify error) in the latter versions.
(In reply to comment #3) > Let me know if you have issues to apply the patch. Olivier, what are the changes in TestVerifier.java and VerifyTests.java for ???
(In reply to comment #9) > Olivier, what are the changes in TestVerifier.java and > VerifyTests.java for ??? This was to try to reduce the number of warnings inside the console when the tests are running.
(In reply to comment #10) > (In reply to comment #9) > > Olivier, what are the changes in TestVerifier.java and > > VerifyTests.java for ??? > This was to try to reduce the number of warnings inside the console when the > tests are running. I see. I caught up with the documentation, reviewed the patch and also studied the stack map table before and after the patch: Things look good and after a bit more testing, I'll be releasing the patch shortly. Dani, this should go into 3.6.2+java7 and 3.7.2 also as verify errors mean the program is dead on arrival realistically speaking. (Comment# 2 does give a workaround.) Let me know your thoughts. Again, thanks for the patch Olivier.
(In reply to comment #11) > (In reply to comment #10) > Dani, this should go into 3.6.2+java7 and 3.7.2 also as verify errors mean > the program is dead on arrival realistically speaking. (Comment# 2 does give > a workaround.) Let me know your thoughts. BTW, the material changes are only those in StackMapFrameCodeStream.java, (~a dozen lines of code) and StackMapAttributeTest.java (~50 lines of test code). The code in the rest of the files in the patch is not germane to this issue and are more over not applicable to maintenance branches.
> Dani, this should go into 3.6.2+java7 and 3.7.2 also as verify errors mean > the program is dead on arrival realistically speaking. (Comment# 2 does give > a workaround.) Let me know your thoughts. +1 for backporting.
Added a new test to cover the case in comment#7, removed the changes not germane to this issue from the patch in comment#3 and released fix in 3.8 stream via commit 524493861edaf12bafa58b5fd6b1f39d5cafdd09.
Ayush, could you please release this in the maintenance branches and also make sure the fix is included in this week's maintenance build ? TIA.
Reopening until backported.
(In reply to comment #10) > (In reply to comment #9) > > Olivier, what are the changes in TestVerifier.java and > > VerifyTests.java for ??? > This was to try to reduce the number of warnings inside the console when the > tests are running. I raised a separate bug 364254 for this side issue.
Released in 3.7 maintenance via commit e75d2e1dc6c4d6085a257406c7d26d4fde4b3631
Verified for 3.8M4 using build I20111202-0800.
Released in 362+java7 branch via commit b75d14e3316776d1f321f4f08efdaaf145fd7019
Verified for 3.7.2 with build M20120118-0800
(In reply to comment #2) > If you're stuck, please use the VM argument -XX:-UseSplitVerifier to run the > program. I confirm that there is no verify error with this option. For posterity's sakes recording here that this workaround does work at least as of Sun JVM 7b147. However, it is NOT supposed to work and does not with IBM JVM.