Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8129740

Incorrect class file created when passing lambda in inner class constructor

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 8-pool, 9
    • Fix Version/s: 9
    • Component/s: tools
    • Labels:
    • Subcomponent:
    • Resolved In Build:
      b93
    • CPU:
      x86_64
    • OS:
      windows_7
    • Verification:
      Verified

      Backports

        Description

        FULL PRODUCT VERSION :
        Reproduced on all of these:

        java version "1.8.0_40"
        Java(TM) SE Runtime Environment (build 1.8.0_40-b26)
        Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

        java version "1.8.0_25"
        Java(TM) SE Runtime Environment (build 1.8.0_25-b18)
        Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

        java version "1.9.0-ea"
        Java(TM) SE Runtime Environment (build 1.9.0-ea-b57)
        Java HotSpot(TM) 64-Bit Server VM (build 1.9.0-ea-b57, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Microsoft Windows [Version 6.1.7600]

        A DESCRIPTION OF THE PROBLEM :
        I compile the following class (CompilerBug.java)

        public class CompilerBug {
        int var = 0;

        public static void main(String[] args) {
        new CompilerBug().new Inner();
        }

        public class Inner {
        public Inner(Runnable r) {}

        public Inner() {
        this(() -> {
        var = 1;
        });
        }
        }
        }

        Compilation finishes without errors. However I see a VerifyError when running the compiled CompilerBug.class

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        1. Create file CompilerBug.java (see "source code" section):

        2. Compile it:
        javac CompilerBug.java

        3. Run the compiled class:
        java CompilerBug

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        Compilation error on step 2 like it's reported by ECJ:

        1. ERROR in C:\projects\Test\src\CompilerBug.java (at line 12)
        this(() -> {
        ^^^^^
        Cannot refer to 'this' nor 'super' while explicitly invoking a constructor

        ACTUAL -
        Compilation goes fine, but when compiled class is launched (step 3) the following error is displayed:

        Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
        Exception Details:
          Location:
            CompilerBug$Inner.<init>(LCompilerBug;)V @3: invokedynamic
          Reason:
            Type uninitializedThis (current frame, stack[2]) is not assignable to 'CompilerBug$Inner'
          Current Frame:
            bci: @3
            flags: { flagThisUninit }
            locals: { uninitializedThis, 'CompilerBug' }
            stack: { uninitializedThis, 'CompilerBug', uninitializedThis }
          Bytecode:
            0000000: 2a2b 2aba 0003 0000 b700 04b1

                at CompilerBug.main(CompilerBug.java:5)

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        public class CompilerBug {
        int var = 0;

        public static void main(String[] args) {
        new CompilerBug().new Inner();
        }

        public class Inner {
        public Inner(Runnable r) {}

        public Inner() {
        this(() -> {
        var = 1;
        });
        }
        }
        }

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

        1. JDK-8129740
          5 kB
          Srikanth Adayapalam

          Issue Links

            Activity

            Hide
            shade Aleksey Shipilev added a comment - - edited
            Submitter pinged me about this bug.
            It reproduces perfectly well on today's self-built jdk9-dev/release, Linux x86_64.
            Please move forward with this bug. Thanks!
            Show
            shade Aleksey Shipilev added a comment - - edited Submitter pinged me about this bug. It reproduces perfectly well on today's self-built jdk9-dev/release, Linux x86_64. Please move forward with this bug. Thanks!
            Hide
            pardesha Pardeep Sharma added a comment -
            Checked this with JDK 8, 8u40, 8u45, 8u60 ea b19, and 9 ea b69 as well and could reproduce the issue on Windows 7 and Linux (64-bit).
            --------------------------
            Output with JDK 8u45:

            $ java CompilerBug

            Exception in thread "main" java.lang.VerifyError: Bad type on operand stack
            Exception Details:
              Location:
                CompilerBug$Inner.<init>(LCompilerBug;)V @3: invokedynamic
              Reason:
                Type uninitializedThis (current frame, stack[2]) is not assignable to 'CompilerBug$Inner'
              Current Frame:
                bci: @3
                flags: { flagThisUninit }
                locals: { uninitializedThis, 'CompilerBug' }
                stack: { uninitializedThis, 'CompilerBug', uninitializedThis }
              Bytecode:
                0000000: 2a2b 2aba 0003 0000 b700 04b1

                    at CompilerBug.main(CompilerBug.java:5)
            Show
            pardesha Pardeep Sharma added a comment - Checked this with JDK 8, 8u40, 8u45, 8u60 ea b19, and 9 ea b69 as well and could reproduce the issue on Windows 7 and Linux (64-bit). -------------------------- Output with JDK 8u45: $ java CompilerBug Exception in thread "main" java.lang.VerifyError: Bad type on operand stack Exception Details:   Location:     CompilerBug$Inner.<init>(LCompilerBug;)V @3: invokedynamic   Reason:     Type uninitializedThis (current frame, stack[2]) is not assignable to 'CompilerBug$Inner'   Current Frame:     bci: @3     flags: { flagThisUninit }     locals: { uninitializedThis, 'CompilerBug' }     stack: { uninitializedThis, 'CompilerBug', uninitializedThis }   Bytecode:     0000000: 2a2b 2aba 0003 0000 b700 04b1         at CompilerBug.main(CompilerBug.java:5)
            Show
            sadayapalam Srikanth Adayapalam added a comment - https://bugs.openjdk.java.net/browse/JDK-8133111
            Hide
            sadayapalam Srikanth Adayapalam added a comment -
            This is a very interesting problem and ECJ behavior is incorrect.

            8.8.7.1 states:

            An explicit constructor invocation statement in a constructor body may not refer
            to any instance variables or instance methods or inner classes declared in this class
            or any superclass, or use this or super in any expression; otherwise, a compiletime
            error occurs.

            This does not forbid use of variables, types, and methods from an enclosing instance
            which must be fully constructed anyway before inner class constructor can be entered.

            Javac's woes in the case of the problem snippet arise from first concluding that the lambda
            must capture `this' that corresponds to Inner (it only needs to capture outer enclosing instance
            that corresponds to CompilerBug) from there deciding to make the implementation method
            an instance method of Inner and then on having to materialize Inner.this before the indy
            call. At that point Inner.this is uninitializedThis and cannot be passed around.

            Fix would involve making the lambda implementation method a static method and arranging
            to capture and pass around outer instance handles and rewriting instance member accesses
            to go through the synthetic locals.

            As an aside see that when the lambda is transformed to an anonymous class both ECJ and
            javac compile it fine.
            Show
            sadayapalam Srikanth Adayapalam added a comment - This is a very interesting problem and ECJ behavior is incorrect. 8.8.7.1 states: An explicit constructor invocation statement in a constructor body may not refer to any instance variables or instance methods or inner classes declared in this class or any superclass, or use this or super in any expression; otherwise, a compiletime error occurs. This does not forbid use of variables, types, and methods from an enclosing instance which must be fully constructed anyway before inner class constructor can be entered. Javac's woes in the case of the problem snippet arise from first concluding that the lambda must capture `this' that corresponds to Inner (it only needs to capture outer enclosing instance that corresponds to CompilerBug) from there deciding to make the implementation method an instance method of Inner and then on having to materialize Inner.this before the indy call. At that point Inner.this is uninitializedThis and cannot be passed around. Fix would involve making the lambda implementation method a static method and arranging to capture and pass around outer instance handles and rewriting instance member accesses to go through the synthetic locals. As an aside see that when the lambda is transformed to an anonymous class both ECJ and javac compile it fine.
            Hide
            sadayapalam Srikanth Adayapalam added a comment -
            An alternate fix would be to promote the lambda implementation method to the outer class.
            Show
            sadayapalam Srikanth Adayapalam added a comment - An alternate fix would be to promote the lambda implementation method to the outer class.
            Hide
            sadayapalam Srikanth Adayapalam added a comment -
            Work in progress. Works for the reported case, but needs polish.
            Show
            sadayapalam Srikanth Adayapalam added a comment - Work in progress. Works for the reported case, but needs polish.
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/dev/langtools/rev/ed4c306ec942
            User: sadayapalam
            Date: 2015-11-09 00:15:36 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/dev/langtools/rev/ed4c306ec942 User: sadayapalam Date: 2015-11-09 00:15:36 +0000
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/ed4c306ec942
            User: lana
            Date: 2015-11-18 23:52:52 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/ed4c306ec942 User: lana Date: 2015-11-18 23:52:52 +0000

              People

              • Assignee:
                sadayapalam Srikanth Adayapalam
                Reporter:
                webbuggrp Webbug Group
              • Votes:
                0 Vote for this issue
                Watchers:
                9 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: