Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 362591

Summary: VerifyError: Inconsistent stackmap frames
Product: [Eclipse Project] JDT Reporter: gino.pel
Component: CoreAssignee: Srikanth Sankaran <srikanth_sankaran>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P3 CC: amj87.iitr, chrriis, daniel_megert, gino.pel, jarthana, Olivier_Thomann, srikanth_sankaran
Version: 3.8   
Target Milestone: 3.6.2+J7   
Hardware: PC   
OS: Windows 7   
Whiteboard:
Attachments:
Description Flags
Proposed fix + regression test none

Description gino.pel CLA 2011-11-01 15:15:18 EDT
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
Comment 1 Srikanth Sankaran CLA 2011-11-02 02:38:34 EDT
Reproduced on HEAD, will follow up for 3.8 M4 and once fix is identified
will consider for 3.7.2 also.
Comment 2 Ayushman Jain CLA 2011-11-02 02:47:32 EDT
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.
Comment 3 Olivier Thomann CLA 2011-11-02 11:27:55 EDT
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.
Comment 4 Srikanth Sankaran CLA 2011-11-03 00:42:45 EDT
(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.)
Comment 5 Christopher Deckers CLA 2011-11-03 06:42:15 EDT
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.
Comment 6 Srikanth Sankaran CLA 2011-11-10 05:01:26 EST
(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.
Comment 7 Srikanth Sankaran CLA 2011-11-15 02:09:33 EST
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);
    }
}
Comment 8 Srikanth Sankaran CLA 2011-11-15 03:02:30 EST
(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.
Comment 9 Srikanth Sankaran CLA 2011-11-15 03:24:42 EST
(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 ???
Comment 10 Olivier Thomann CLA 2011-11-15 07:28:25 EST
(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.
Comment 11 Srikanth Sankaran CLA 2011-11-15 08:01:23 EST
(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.
Comment 12 Srikanth Sankaran CLA 2011-11-15 08:23:48 EST
(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.
Comment 13 Dani Megert CLA 2011-11-15 09:30:00 EST
> 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.
Comment 14 Srikanth Sankaran CLA 2011-11-15 23:21:45 EST
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.
Comment 15 Srikanth Sankaran CLA 2011-11-15 23:22:50 EST
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.
Comment 16 Ayushman Jain CLA 2011-11-16 01:51:34 EST
Reopening until backported.
Comment 17 Srikanth Sankaran CLA 2011-11-21 00:52:19 EST
(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.
Comment 18 Ayushman Jain CLA 2011-11-23 01:59:37 EST
Released in 3.7 maintenance via commit e75d2e1dc6c4d6085a257406c7d26d4fde4b3631
Comment 19 Ayushman Jain CLA 2011-12-06 09:36:55 EST
Verified for 3.8M4 using build I20111202-0800.
Comment 20 Ayushman Jain CLA 2011-12-08 05:05:40 EST
Released in 362+java7 branch via commit b75d14e3316776d1f321f4f08efdaaf145fd7019
Comment 21 Jay Arthanareeswaran CLA 2012-01-19 01:56:48 EST
Verified for 3.7.2 with build M20120118-0800
Comment 22 Srikanth Sankaran CLA 2012-02-07 01:10:35 EST
(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.