JDK-8067429 : java.lang.VerifyError: Inconsistent stackmap frames at branch target
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 7u71,8u25
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86_64
  • Submitted: 2014-12-09
  • Updated: 2019-11-11
  • Resolved: 2015-01-09
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9 Other
9 b46Fixed openjdk8u242Fixed
Description
FULL PRODUCT VERSION :
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux steve-virtual-machine 3.5.0-17-generic #28-Ubuntu SMP Tue Oct 9 19:31:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
(

EXTRA RELEVANT SYSTEM CONFIGURATION :
It is believed this issue is machine/hardware independent.

A DESCRIPTION OF THE PROBLEM :
When the program below is compiled, a class file is produced. However, when this class is loaded (by running the main inside it for example), it produces a verifier error.

This fails for Java7 and Java8, although not Java6.

BTW, I do not know if this is a compiler bug, or a verifier bug.

It should be noted that the example below is a refinement of the result of some automatic code generation. As such, it is merely an example of a non-working method. The 'real world' effect of this is hat the code generation for some input is correct java syntax in that it goes through the compiler, but it does not execute at all.

REGRESSION.  Last worked in version 6u45

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the example code, and try to execute it.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
$ javac VerifyBug.java
$ java VerifyBug

ACTUAL -
$ javac VerifyBug.java
$ java VerifyBug
Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames at branch target 84
Exception Details:
  Location:
    VerifyBug.problematicMethod(I)V @84: goto
  Reason:
    Type top (current frame, locals[4]) is not assignable to long (stack map, locals[4])
  Current Frame:
    bci: @51
    flags: { }
    locals: { 'VerifyBug', integer }
    stack: { integer }
  Stackmap Frame:
    bci: @84
    flags: { }
    locals: { 'VerifyBug', integer, top, top, long, long_2nd }
    stack: { }
  Bytecode:
    0000000: 1bab 0000 0000 0028 0000 0002 0000 0002
    0000010: 0000 001e 0000 0003 0000 001b a700 0007
    0000020: 3604 1b10 109f 0007 b1a7 0000 1b10 079f
    0000030: 0028 1bab 0000 0024 0000 0002 0000 0001
    0000040: 0000 0019 0000 0002 0000 0021 1400 0237
    0000050: 04a7 0006 a700 03b1                    
  Stackmap Table:
    same_frame(@28)
    same_frame(@31)
    same_frame(@41)
    same_frame(@44)
    same_frame(@76)
    append_frame(@84,Top,Top,Long)
    chop_frame(@87,3)

	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2615)
	at java.lang.Class.getMethod0(Class.java:2856)
	at java.lang.Class.getMethod(Class.java:1668)
	at sun.launcher.LauncherHelper.getMainMethod(LauncherHelper.java:494)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:486)



REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public class VerifyBug {
  public static void main(String[] args) {
  }
  private void problematicMethod(int p) {
    switch (p) {
      case 3:
	long n;
	while (true) {
	  if (false) {
	    break;
	  }
	}
	break;
      case 2:
loop: while (true) {
      while (true) {
	  int i = 4;
	  if (p != 16) {
	    return;
	  }
	  break loop;
	}
      }
      break;
      default:
      while (true) {
	if (false) {
	  break;
	}
      }
      break;
    }
    long b;
    if (p != 7) {
      switch (p) {
	case 1:
	  long a = 17;
	  break;
	case 2:
	  break;
	default:
	  break;
      }
    }
  }
}


---------- END SOURCE ----------


Comments
I'm not sure what process you were following for 11u, but they should be the same (though obviously differently named labels!)
16-09-2019

Ah I see, this is a bit different to jdk11u then it seems. thanks, I will post a request to Andrew Haley/Andrew Hughes Thanks Jan, Srikanth
10-09-2019

Thanks for the clarification Jan. So Andrew, could you ping the maintainers about this ? Thanks.
10-09-2019

Hi Andrew, Per: https://wiki.openjdk.java.net/display/jdk8u the maintainers of 8u need to add the "jdk8u-fix-yes" label (or "jdk8u-fix-no") label (see "The maintainer will either approve this by setting jdk8u-fix-yes or reject it by setting jdk8u-fix-no." from the above page.)
10-09-2019

[~vromero] Hi Vicente, you have reviewed the RFR here: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-August/010061.html and responded with a +1. Being a 8u reviewer, could you set the suitable labels (jdk8u-fix-yes).
10-09-2019

Hello Andrew, As far as I can tell, you need to (a) contact a 8u reviewer to have the jdk8u-fix-yes label fixed on this bug, You have a +1 from Vicente Romero. He can do this for you. (b) Apart from review, you need approval from maintainers of 8u which would be from Andrew Haley/Andrew Hughes (c) They may also advise you on the exact logistics of the push. HTH. I will contact Vicente on your behalf rightaway.
10-09-2019

Hi Srikanth, I thought I had followed the documented process, aren't these 2 reviews from Vicente Romero and Aleksey Shipilev for this on jdk8u-dev sufficient? https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-August/010061.html https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-August/010075.html Thanks Andrew
10-09-2019

Hi Andrew, I apologize for the delay in responding. Please see https://wiki.openjdk.java.net/display/jdk8u for the process to be followed. In particular, the Fix Approvals section. You need to get suitable approvals from the concerned gatekeeping folk. You can browse here some recent activity seeking backport approvals: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-September
10-09-2019

Fix Request any update on jdk8u-fix-request approval?
09-09-2019

Fix Request Please can I request a backport for 8067429. We have had problem reports from clients seeing this issue with jdk8. The patch is essentially the same as published to jdk9+, but jdk8 the file paths are in a different location. I have built and tested all "tier1" and "langtools_all" successfully, and the new testcase passes. Updated webrev for jdk8u: http://cr.openjdk.java.net/~aleonard/8067429/webrev.00 8u RFR: https://mail.openjdk.java.net/pipermail/jdk8u-dev/2019-August/010061.html
20-08-2019

Gen.visitLabelled and Gen.visitSwitch are missing some clean up code (cf Gen.genLoop) to purge local variables that have gone out of scope.
29-12-2014

Basically the problem stems from incorrect manipulation of Code.State.defined bits. When we have a branch from a region that has more definitions into a branch with fewer definitions, we incorrectly carry along the definitions from the jump site into the target site. This block of code in com.sun.tools.javac.jvm.Code#resolve(com.sun.tools.javac.jvm.Code.Chain, int): if (state != newState) { setDefined(newState.defined); state = newState; pendingStackMap = needStackMap; } looks suspect to me. So does this block of code in for (int adr = diff.nextBit(0); adr >= 0; adr = diff.nextBit(adr+1)) { if (adr >= nextreg) state.defined.excl(adr); else if (state.defined.isMember(adr)) setUndefined(adr); else setDefined(adr); } in particular the last call to setDefined. As a result of this, in Gen.visitSwitch Code.State stateSwitch = code.state.dup(); we compute bogus state for the last switch entry state.
24-12-2014

Basically the problem stems from incorrect manipulation of Code.State.defined bits. When we have a branch from a region that has more definitions into a branch with fewer definitions, we incorrectly carry along the definitions from the jump site into the target site. This block of code in com.sun.tools.javac.jvm.Code#resolve(com.sun.tools.javac.jvm.Code.Chain, int): {code} if (state != newState) { setDefined(newState.defined); state = newState; pendingStackMap = needStackMap; } {code} looks suspect to me. So does this block of code in {code} for (int adr = diff.nextBit(0); adr >= 0; adr = diff.nextBit(adr+1)) { if (adr >= nextreg) state.defined.excl(adr); else if (state.defined.isMember(adr)) setUndefined(adr); else setDefined(adr); } {code} in particular the last call to setDefined. As a result of this, in Gen.visitSwitch Code.State stateSwitch = code.state.dup(); we compute bogus state for the last switch entry state.
24-12-2014

Checked this with JDK 6u45, 7u72, 8u40 and 9 in Windows and Linux and confirms the issue.
15-12-2014