Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 361053 - java.lang.VerifyError on try-with-resources
Summary: java.lang.VerifyError on try-with-resources
Status: VERIFIED FIXED
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.8   Edit
Hardware: PC All
: P3 critical (vote)
Target Milestone: 3.6.2+J7   Edit
Assignee: Srikanth Sankaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 364008 (view as bug list)
Depends on:
Blocks:
 
Reported: 2011-10-15 09:37 EDT by Siegmar Alber CLA
Modified: 2012-01-19 01:03 EST (History)
6 users (show)

See Also:
Olivier_Thomann: review+


Attachments
Class producing error (318 bytes, application/octet-stream)
2011-10-15 09:38 EDT, Siegmar Alber CLA
no flags Details
Stack trace (516 bytes, text/plain)
2011-10-15 09:39 EDT, Siegmar Alber CLA
no flags Details
Patch under test (4.08 KB, patch)
2011-11-18 08:56 EST, Srikanth Sankaran CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Siegmar Alber CLA 2011-10-15 09:37:28 EDT
Build Identifier: 20110916-0149

When running attached Java class a "java.lang.VerifyError: Inconsistent stackmap frames" occurs. When compiling with javac all works as expected.

Tried with
* openjdk version "1.7.0-b213" and Eclipse 20110916-0149 on Mac OS X
* java build 1.7.0-b147 and Eclipse 20110916-0149 on Windows 7

Class producing the error and stack trace is attached.

Reproducible: Always

Steps to Reproduce:
1. Create new Java project (Java 7)
2. Create attached class
3. Run it
Comment 1 Siegmar Alber CLA 2011-10-15 09:38:47 EDT
Created attachment 205251 [details]
Class producing error
Comment 2 Siegmar Alber CLA 2011-10-15 09:39:43 EDT
Created attachment 205252 [details]
Stack trace
Comment 3 Srikanth Sankaran CLA 2011-10-17 00:49:05 EDT
I'll follow up.
Comment 4 Olivier Thomann CLA 2011-10-17 09:30:11 EDT
This works in HEAD. Likely a dup of bug 359495.
Comment 5 Srikanth Sankaran CLA 2011-10-18 00:03:33 EDT
(In reply to comment #4)
> This works in HEAD. Likely a dup of bug 359495.

That was what I thought, but I did manage to reproduce it on HEAD.
I'll try again today to reconfirm.
Comment 6 Srikanth Sankaran CLA 2011-10-18 04:10:20 EDT
(In reply to comment #5)
> (In reply to comment #4)
> > This works in HEAD. Likely a dup of bug 359495.
> 
> That was what I thought, but I did manage to reproduce it on HEAD.
> I'll try again today to reconfirm.

I get a verify error with both IBM JVM and Sun JVM.

If the resources section has only one resource or if the
boolean foo was made non-final and initialized, then the
verify error does not occur.
Comment 7 Olivier Thomann CLA 2011-10-18 08:33:03 EDT
Can you provide a test case that is failing ?
Comment 8 Srikanth Sankaran CLA 2011-10-18 09:28:01 EDT
(In reply to comment #7)
> Can you provide a test case that is failing ?

The test from comment# 0 fails for me with both IBM and Sun JREs.
I'll ask Ayush to also test so we can eliminate some set up issue
on my side. Ayush, can you please see if you can reproduce this ?
Comment 9 Olivier Thomann CLA 2011-10-18 09:35:29 EDT
Ok, it fails if all locals are preserved. If unused locals are optimized out, the code generation is fine.
Do you want me to take a look at this one?
Comment 10 Olivier Thomann CLA 2011-10-18 09:45:48 EDT
The stack map table is too simple. I think the problem comes from the locals initialization ranges. Since the stack map frames are based on those ranges, it could explain why there is a problem.
Comment 11 Srikanth Sankaran CLA 2011-10-18 09:48:19 EDT
(In reply to comment #9)
> Ok, it fails if all locals are preserved. If unused locals are optimized out,
> the code generation is fine.
> Do you want me to take a look at this one?

Sure, if you have the cycles that would be appreciated, given we are close
to milestone builds. Thanks Olivier.
Comment 12 Srikanth Sankaran CLA 2011-11-17 07:15:52 EST
Another test case from bug 364008

public class Bug {

  public static void main(final String[] args) throws IOException {
    byte[] data;
    try (final ByteArrayOutputStream os = new ByteArrayOutputStream();
         final FileOutputStream out = new FileOutputStream("test.dat")) {
      data = os.toByteArray();
    }
  }
}
Comment 13 Srikanth Sankaran CLA 2011-11-17 07:17:10 EST
*** Bug 364008 has been marked as a duplicate of this bug. ***
Comment 14 Srikanth Sankaran CLA 2011-11-18 01:48:31 EST
For posterity, here are some variously annotated notes that highlight the
problem. The disassembler output has been annotated to show the effects of
the transformation described in https://bugs.eclipse.org/bugs/show_bug.cgi?id=338402#c16

There are two things that sick out:

(1) frame at 119 looks suspicious - where did the local int come from ?
(2) edge from 52-119 obviously is problematic.

Fix under investigation.


Exception in thread "main" java.lang.VerifyError: JVMVRFY012 stack shape inconsistent; class=X, method=main([Ljava/lang/String;)V, pc=52
	at java.lang.J9VMInternals.verifyImpl(Native Method)
	at java.lang.J9VMInternals.verify(J9VMInternals.java:90)
	at java.lang.J9VMInternals.initialize(J9VMInternals.java:167)

Exception in thread "main" java.lang.VerifyError: Inconsistent stackmap frames a
t branch target 119 in method X.main([Ljava/lang/String;)V at offset 52
        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)


Classfile /C:/jtests/X.class
  Last modified Nov 16, 2011; size 955 bytes
  MD5 checksum 0e58850442c5401c5e66d4aa9e656788
  Compiled from "X.java"
public class X implements java.lang.AutoCloseable
  SourceFile: "X.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER

Constant pool:
   #1 = Class              #2             //  X
   #2 = Utf8               X
   #3 = Class              #4             //  java/lang/Object
   #4 = Utf8               java/lang/Object
   #5 = Class              #6             //  java/lang/AutoCloseable
   #6 = Utf8               java/lang/AutoCloseable
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Methodref          #3.#11         //  java/lang/Object."<init>":()V
  #11 = NameAndType        #7:#8          //  "<init>":()V
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               LX;
  #16 = Utf8               close
  #17 = Utf8               Exceptions
  #18 = Class              #19            //  java/lang/Exception
  #19 = Utf8               java/lang/Exception
  #20 = Methodref          #18.#11        //  java/lang/Exception."<init>":()V
  #21 = Utf8               main
  #22 = Utf8               ([Ljava/lang/String;)V
  #23 = Methodref          #1.#11         //  X."<init>":()V
  #24 = Methodref          #1.#25         //  X.close:()V
  #25 = NameAndType        #16:#8         //  close:()V
  #26 = Methodref          #27.#29        //  java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V
  #27 = Class              #28            //  java/lang/Throwable
  #28 = Utf8               java/lang/Throwable
  #29 = NameAndType        #30:#31        //  addSuppressed:(Ljava/lang/Throwable;)V
  #30 = Utf8               addSuppressed
  #31 = Utf8               (Ljava/lang/Throwable;)V
  #32 = Utf8               args
  #33 = Utf8               [Ljava/lang/String;
  #34 = Utf8               foo
  #35 = Utf8               Z
  #36 = Utf8               a
  #37 = Utf8               b
  #38 = Utf8               exception
  #39 = Utf8               Ljava/lang/Exception;
  #40 = Utf8               StackMapTable
  #41 = Class              #33            //  "[Ljava/lang/String;"
  #42 = Utf8               SourceFile
  #43 = Utf8               X.java
{
  public static void main(java.lang.String[]);
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=2, locals=6, args_size=1
         0: aconst_null   
         1: astore_2                                                                       L2# _primaryExceptionVariable = null;
         2: aconst_null   
         3: astore_3                                                                       L3# caughtThrowableVariable = null;
         4: new           #1                  // class X
         7: dup           
         8: invokespecial #23                 // Method "<init>":()V
        11: astore        4                                                                a = new X();
        13: new           #1                  // class X
        16: dup           
        17: invokespecial #23                 // Method "<init>":()V
        20: astore        5                                                                b = new X();

------------------  Try body as given by user -----
        22: iconst_1      
        23: istore_1                                                                       foo = true;
-------------------- Auto close of b --------------
        24: aload         5
        26: ifnull        50
        29: aload         5
        31: invokevirtual #24                 // Method close:()V                          if (b != null) b.close();
        34: goto          50
------------------  catch block --------------------

          locals = [ class "[Ljava/lang/String;", top, class java/lang/Throwable, class java/lang/Throwable, class X, class X ]
          stack = [ class java/lang/Throwable ]


        37: astore_2                                                                      L2#  _primaryExceptionVariable = exceptionCaught.
        38: aload         5
        40: ifnull        48
        43: aload         5
        45: invokevirtual #24                 // Method close:()V                          if (b != null) b.close();

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable, class X (a) ]
          stack [empty]

        48: aload_2       
        49: athrow                                                                        throw primaryException;

---------- Normal automatic resource closure for a -----------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable, class X (a) ]
          stack [empty]

        50: aload         4
        52: ifnull        119
        55: aload         4
        57: invokevirtual #24                 // Method close:()V                         if (a != null) a.close();
        60: goto          119
----------------------------------------------------------------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable, class X (a) ]
          stack = [ class java/lang/Throwable ]

        63: astore_3                                                                      L3#  caughtThrowableVariable = exceptionCaught
        64: aload_2       
        65: ifnonnull     73
        68: aload_3       
        69: astore_2                                                                      if (primaryException == null) primaryException = caughtThrowableVariable;
        70: goto          83

-------------------------- Suppression list management -------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable, class X (a) ]
          stack = [ class java/lang/Throwable ]

        73: aload_2       
        74: aload_3       
        75: if_acmpeq     83
        78: aload_2       
        79: aload_3       
        80: invokevirtual #26                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V     if (_primaryException != caughtThrowableVariable) { _primaryException.addSuppressed(caughtThrowableVariable); }

------------------------------------------------------------------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable, class X (a) ]
          stack = [ class java/lang/Throwable ]

        83: aload         4
        85: ifnull        93
        88: aload         4
        90: invokevirtual #24                 // Method close:()V                   if (a != null) a.close();

-----------------------------------------------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable]
          stack = [ Empty ]

        93: aload_2       
        94: athrow                                                                  throw primaryException;

----------------------------------------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable]
          stack = [ class java/lang/Throwable ]

        95: astore_3                                                                 L3#  caughtThrowableVariable = exceptionCaught 
        96: aload_2       
        97: ifnonnull     105
       100: aload_3       
       101: astore_2                                                               if (primaryException == null) primaryException = caughtThrowableVariable;
       102: goto          115

-----------------------------------------------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable]
          stack = [ class java/lang/Throwable ]

       105: aload_2       
       106: aload_3       
       107: if_acmpeq     115
       110: aload_2       
       111: aload_3       
       112: invokevirtual #26                 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V     if (_primaryException != caughtThrowableVariable) { _primaryException.addSuppressed(caughtThrowableVariable); }

--------------------------------------------------------

          locals = [ class "[Ljava/lang/String;", class java/lang/Throwable, class java/lang/Throwable]
          stack = [ class java/lang/Throwable ]

       115: aload_2       
       116: athrow                                                                 throw primaryException;

---------------------- User's catch block --------------------
          locals = [ class "[Ljava/lang/String;" ]
          stack = [ class java/lang/Exception ]
       117: astore_2      
       118: return        
---------------------------------------------------------------
          locals = [ class "[Ljava/lang/String;" , int ]
          stack = [ EMPTY ]
       119: return        
      Exception table:
         from    to  target type
            22    24    37   any
            13    50    63   any
             4    95    95   any
             0   117   117   Class java/lang/Exception
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
               0     120     0  args   [Ljava/lang/String;
              24      13     1   foo   Z
             119       1     1   foo   Z
              13      80     4     a   LX;
              22      26     5     b   LX;
             118       1     2 exception   Ljava/lang/Exception;
      StackMapTable: number_of_entries = 12

--------------------
           frame_type = 255 /* full_frame */
          offset_delta = 37
          locals = [ class "[Ljava/lang/String;", top, class java/lang/Throwable, class java/lang/Throwable, class X, class X ]
          stack = [ class java/lang/Throwable ]
--------------------

           frame_type = 250 /* chop */
          offset_delta = 10

-------------------

           frame_type = 1 /* same */

-----------------------

           frame_type = 76 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
-------------------------
           frame_type = 9 /* same */
-------------------------
           frame_type = 9 /* same */
--------------------------
           frame_type = 250 /* chop */
          offset_delta = 9
-----------------------------
           frame_type = 65 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
------------------------------
           frame_type = 9 /* same */
-------------------------------
           frame_type = 9 /* same */
-------------------------------
           frame_type = 255 /* full_frame */
          offset_delta = 1
          locals = [ class "[Ljava/lang/String;" ]
          stack = [ class java/lang/Exception ]
----------------------------------
           frame_type = 252 /* append */
             offset_delta = 1
        locals = [ int ]
}
Comment 15 Srikanth Sankaran CLA 2011-11-18 01:50:17 EST
(In reply to comment #14)
> For posterity, here are some variously annotated notes that highlight the
> problem. The disassembler output has been annotated to show the effects of
> the transformation described in
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=338402#c16

Just a note that the transformation referred to above is missing in null
checks prior to close. (the generated code does the right thing)
Comment 16 Srikanth Sankaran CLA 2011-11-18 02:03:04 EST
(In reply to comment #14)
> (1) frame at 119 looks suspicious - where did the local int come from ?

int being vm type for boolean, it appears that we are claiming the boolean
foo is in range after the twr - which is blatantly not true.

Investigating the initialization ranges ...
Comment 17 Srikanth Sankaran CLA 2011-11-18 08:56:17 EST
Created attachment 207216 [details]
Patch under test

With this patch both the issues reported in current bug and its
duplicate are fixed.

Try*Tests pass, Running all JDT/Core tests now.
Comment 18 Srikanth Sankaran CLA 2011-11-18 08:58:33 EST
(In reply to comment #14)

> There are two things that sick out:
> 
> (1) frame at 119 looks suspicious - where did the local int come from ?

This int local is indeed correct, I had missed that the catch block was
returning.

> (2) edge from 52-119 obviously is problematic.

This is problematic and is fixed by the patch.
Comment 19 Srikanth Sankaran CLA 2011-11-18 11:02:22 EST
Passes all tests. 

Olivier, please review this small patch - TIA.

Basically, given that the single try statement is getting transformed into
several nested try-catch-finally blocks as described in bug 338402 comment 16,
we need to reset the type states whenever we are fully done with a nested
try block. Presently, it is left at the type state corresponding to the catch
block of the nested try block.
Comment 20 Olivier Thomann CLA 2011-11-18 15:03:12 EST
Patch looks good. Local initialization ranges look better.
Comment 21 Srikanth Sankaran CLA 2011-11-18 20:34:29 EST
Released fix and tests in 3.8 stream via commit 7a907611eaa1f47df5cf7c04e21c82794b93d39a.

Ayush, please also release for 3.7.2 and 3.6.2+java7 as this is
a serious issue and has been reported from multiple sources.
Comment 22 Ayushman Jain CLA 2011-11-23 02:56:01 EST
Released in 3.7 maintenance via commit 7db712d6cc704573774e9fbd29d0c7b0d40d6d3c
Comment 23 Satyam Kandula CLA 2011-12-06 06:35:57 EST
Verified for 3.8M4 using build I20111202-0800
Comment 24 Ayushman Jain CLA 2011-12-08 04:57:30 EST
Released in 3.6.2+java7 branch via commit c07bf8c2ab7dee126a5194e2fc5ef6123e172c13
Comment 25 Satyam Kandula CLA 2012-01-19 01:03:10 EST
Verified for 3.7.2RC2 using build M20120118-0800