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

StackOverflowError at com.sun.tools.javac.code.Types.lub

    Details

    • Subcomponent:
    • Resolved In Build:
      b36
    • Verification:
      Verified

      Backports

        Description

        When trying to build our project's code using JDK 8u20's, javac crashes with a StackOverflowError.
        This worked fine in all prior versions of t he JDK (e.g. 8u11, 7u67,
        6u45, etc.) so this is a regression in the compiler.
        This happens on RHEL 5.10 64-bit, CentOS 6.5 32-bit & 64-bit, RHEL 7
        64-bit, etc.

        java version "1.8.0_20"
        Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
        Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
        javac 1.8.0_20

        The system is out of resources.
        Consult the following stack trace for details.
        java.lang.StackOverflowError
                at com.sun.tools.javac.code.Types.lub(Types.java:3532)
                at com.sun.tools.javac.code.Types.lub(Types.java:3616)
                at com.sun.tools.javac.code.Types.lub(Types.java:3616)
                at com.sun.tools.javac.code.Types.lub(Types.java:3616)
                at com.sun.tools.javac.code.Types.lub(Types.java:3616)
        ...

        HOW TO REPRODUCE:

        To reproduce issue, download tarball at following URL:

        http://nextmidas.techma.com/nextmidas/nxm350/nxm350_showing_jdk8u20_javac_bug.tar.gz
        (the original project has been simplified in order to make it easier to reproduce).

        Then:

        1. extract tarball
        2. cd to directory (nxmxxx)
        3. javac -classpath . -source 1.6 nxm/sys/lib/KeyObject.java

        I think one of the key thing here is the use of -source 1.6 or -or-
        -source 1.7 when using JDK 8u20's javac.

          Issue Links

            Activity

            Hide
            mcimadamore Maurizio Cimadamore added a comment -
            Minimal test case:

            class Test {
                Class<?> test(Class<Double> cd, Class<? extends double[]> cdarr) {
                    return (false) ? cd : cdarr;
                }
            }

            Needs to be compiled with -source 7 in order to reproduce the crash.
            Show
            mcimadamore Maurizio Cimadamore added a comment - Minimal test case: class Test {     Class<?> test(Class<Double> cd, Class<? extends double[]> cdarr) {         return (false) ? cd : cdarr;     } } Needs to be compiled with -source 7 in order to reproduce the crash.
            Hide
            mcimadamore Maurizio Cimadamore added a comment -
            The following test case:

            class Test {
                <Z> void choose(Z z1, Z z2) { }

                void test(Class<Double> cd, Class<? extends double[]> cdarr) {
                    choose(cd, cdarr);
                }
            }

            Reproduces the crash even without the source flag - lub() seems to be broken for these specific inputs - possibly as a result of this fix JDK-8033718
            Show
            mcimadamore Maurizio Cimadamore added a comment - The following test case: class Test {     <Z> void choose(Z z1, Z z2) { }     void test(Class<Double> cd, Class<? extends double[]> cdarr) {         choose(cd, cdarr);     } } Reproduces the crash even without the source flag - lub() seems to be broken for these specific inputs - possibly as a result of this fix JDK-8033718
            Hide
            mcimadamore Maurizio Cimadamore added a comment -
            Correction - the offending changeset is this one:

            http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/abbc15936e1b

            Which as been introduced to fix JDK-8042338.
            Show
            mcimadamore Maurizio Cimadamore added a comment - Correction - the offending changeset is this one: http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/abbc15936e1b Which as been introduced to fix JDK-8042338 .
            Hide
            mcimadamore Maurizio Cimadamore added a comment -
            The specific change that introduced the regression is the following (inside Types.merge):

            - m = new WildcardType(lub(upperBound(act1.head),
            - upperBound(act2.head)),
            + m = new WildcardType(lub(wildUpperBound(act1.head),
            + wildUpperBound(act2.head)),

            When invoked on Class<Double>, Class<#CAP>, where #CAP <: double[], Types.merge used to call Types.upperBound on both type-arguments and then apply lub on the results - which meant:

            lub(Double, double[])

            Now, since we use wildUpperBound instead, we only rewrite wildcard upper bounds, which leads to lub being called with the following parameters:

            lub(Double, #CAP1)

            From here on, the compiler never terminates, as lub is first rewriting #CAP as its upper bound (double[]) but then in this code:

            for (Type t : ts) {
                if (!t.hasTag(ARRAY)) // Filter out any arrays
                    classes = classes.prepend(t);
                }
            }
            return lub(classes);

            We fail to 'exclude' #CAP from the list because we fail to see that it's a var with an array bound. Hence, we loop forever with the same types being passed to lub.
            Show
            mcimadamore Maurizio Cimadamore added a comment - The specific change that introduced the regression is the following (inside Types.merge): - m = new WildcardType(lub(upperBound(act1.head), - upperBound(act2.head)), + m = new WildcardType(lub(wildUpperBound(act1.head), + wildUpperBound(act2.head)), When invoked on Class<Double>, Class<#CAP>, where #CAP <: double[], Types.merge used to call Types.upperBound on both type-arguments and then apply lub on the results - which meant: lub(Double, double[]) Now, since we use wildUpperBound instead, we only rewrite wildcard upper bounds, which leads to lub being called with the following parameters: lub(Double, #CAP1) From here on, the compiler never terminates, as lub is first rewriting #CAP as its upper bound (double[]) but then in this code: for (Type t : ts) {     if (!t.hasTag(ARRAY)) // Filter out any arrays         classes = classes.prepend(t);     } } return lub(classes); We fail to 'exclude' #CAP from the list because we fail to see that it's a var with an array bound. Hence, we loop forever with the same types being passed to lub.
            Hide
            mcimadamore Maurizio Cimadamore added a comment -
            Note - lub always had this bug with infinite recursion - I tried the following with JDK 7 (1.7.0_65):

            import java.util.*;

            class Test {
                void m(List<? extends double[]> ld, Double d) {
                    Object o = true ? ld.get(0) : d;
                }
            }

            And the crash is there (albeit with different line numbers, of course).

            We can conclude that JDK-8042338 only exposed an existing javac issue that would have been otherwise very hard to reproduce. The root fix is to address the problem in lub.

            Show
            mcimadamore Maurizio Cimadamore added a comment - Note - lub always had this bug with infinite recursion - I tried the following with JDK 7 (1.7.0_65): import java.util.*; class Test {     void m(List<? extends double[]> ld, Double d) {         Object o = true ? ld.get(0) : d;     } } And the crash is there (albeit with different line numbers, of course). We can conclude that JDK-8042338 only exposed an existing javac issue that would have been otherwise very hard to reproduce. The root fix is to address the problem in lub.
            Hide
            mcimadamore Maurizio Cimadamore added a comment -
            The likely cause as to why this has never been reported before is that the following code:

            import java.util.*;

            class Test {
                <Z> void choose(Z z1, Z z2) { }

                void m(List<? extends double[]> ld, Double d) {
                    choose(ld.get(0), d);
                }
            }

            Works correctly in all releases; due to a known discrepancy between the JLS and javac, javac would call the upper bound on the actual argument, hence turning #CAP into double[] before calling lub.
            Show
            mcimadamore Maurizio Cimadamore added a comment - The likely cause as to why this has never been reported before is that the following code: import java.util.*; class Test {     <Z> void choose(Z z1, Z z2) { }     void m(List<? extends double[]> ld, Double d) {         choose(ld.get(0), d);     } } Works correctly in all releases; due to a known discrepancy between the JLS and javac, javac would call the upper bound on the actual argument, hence turning #CAP into double[] before calling lub.
            Hide
            mcimadamore Maurizio Cimadamore added a comment -
            Another related lub failure present in all releases (in 8 you need so set -source 7 to reproduce):

            import java.util.*;

            class Test {
                <Z> void m(Z z) { }

                void test(List<? extends double[]> l) {
                    Object o = true ? l.get(0) : l.get(0);
                }
            }

            Gives:

            An exception has occurred in the compiler (1.7.0_65). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you.
            java.lang.NullPointerException
            at com.sun.tools.javac.code.Types.lub(Types.java:2886)
            at com.sun.tools.javac.code.Types.lub(Types.java:2844)
            at com.sun.tools.javac.comp.Attr.condType1(Attr.java:1278)
            at com.sun.tools.javac.comp.Attr.condType(Attr.java:1201)
            at com.sun.tools.javac.comp.Attr.visitConditional(Attr.java:1182)
            at com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1108)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418)
            at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:449)
            at com.sun.tools.javac.comp.Attr.visitVarDef(Attr.java:887)
            at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:725)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418)
            at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:480)
            at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:496)
            at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:918)
            at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:781)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418)
            at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:480)
            at com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:836)
            at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:669)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431)
            at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418)
            at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:480)
            at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:3250)
            at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:3173)
            at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:3109)
            at com.sun.tools.javac.comp.Attr.attrib(Attr.java:3083)
            at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1184)
            at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:870)
            at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:829)
            at com.sun.tools.javac.main.Main.compile(Main.java:439)
            at com.sun.tools.javac.main.Main.compile(Main.java:353)
            at com.sun.tools.javac.main.Main.compile(Main.java:342)
            at com.sun.tools.javac.main.Main.compile(Main.java:333)
            at com.sun.tools.javac.Main.compile(Main.java:76)
            at com.sun.tools.javac.Main.main(Main.java:61)

            Again, this is caused by the fact that javac is trying to access the element type of an array but it gets a captured variable (whose bound is an array) instead; hence, elementType returns null and lub NPEs.
            Show
            mcimadamore Maurizio Cimadamore added a comment - Another related lub failure present in all releases (in 8 you need so set -source 7 to reproduce): import java.util.*; class Test {     <Z> void m(Z z) { }     void test(List<? extends double[]> l) {         Object o = true ? l.get(0) : l.get(0);     } } Gives: An exception has occurred in the compiler (1.7.0_65). Please file a bug at the Java Developer Connection ( http://java.sun.com/webapps/bugreport ) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you. java.lang.NullPointerException at com.sun.tools.javac.code.Types.lub(Types.java:2886) at com.sun.tools.javac.code.Types.lub(Types.java:2844) at com.sun.tools.javac.comp.Attr.condType1(Attr.java:1278) at com.sun.tools.javac.comp.Attr.condType(Attr.java:1201) at com.sun.tools.javac.comp.Attr.visitConditional(Attr.java:1182) at com.sun.tools.javac.tree.JCTree$JCConditional.accept(JCTree.java:1108) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418) at com.sun.tools.javac.comp.Attr.attribExpr(Attr.java:449) at com.sun.tools.javac.comp.Attr.visitVarDef(Attr.java:887) at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:725) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418) at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:480) at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:496) at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:918) at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:781) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418) at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:480) at com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:836) at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:669) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:431) at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:418) at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:480) at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:3250) at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:3173) at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:3109) at com.sun.tools.javac.comp.Attr.attrib(Attr.java:3083) at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1184) at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:870) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:829) at com.sun.tools.javac.main.Main.compile(Main.java:439) at com.sun.tools.javac.main.Main.compile(Main.java:353) at com.sun.tools.javac.main.Main.compile(Main.java:342) at com.sun.tools.javac.main.Main.compile(Main.java:333) at com.sun.tools.javac.Main.compile(Main.java:76) at com.sun.tools.javac.Main.main(Main.java:61) Again, this is caused by the fact that javac is trying to access the element type of an array but it gets a captured variable (whose bound is an array) instead; hence, elementType returns null and lub NPEs.
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/dev/langtools/rev/6f666e88a0f4
            User: mcimadamore
            Date: 2014-10-14 11:04:18 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/dev/langtools/rev/6f666e88a0f4 User: mcimadamore Date: 2014-10-14 11:04:18 +0000
            Hide
            hgupdate HG Updates added a comment -
            URL: http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/6f666e88a0f4
            User: lana
            Date: 2014-10-22 18:55:28 +0000
            Show
            hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/6f666e88a0f4 User: lana Date: 2014-10-22 18:55:28 +0000

              People

              • Assignee:
                mcimadamore Maurizio Cimadamore
                Reporter:
                mcimadamore Maurizio Cimadamore
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: