JDK-6586091 : javac crashes with StackOverflowError
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6u1
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2007-07-27
  • Updated: 2011-05-18
  • Resolved: 2011-05-18
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 7
7 b39Fixed
Related Reports
Relates :  
Relates :  
Description
I have a non-trivial source tree that crashes javac with the following stack trace:

The system is out of resources.
Consult the following stack trace for details.
java.lang.StackOverflowError
        at com.sun.tools.javac.code.Type$WildcardType.accept(Type.java:415)
        at com.sun.tools.javac.code.Types$MapVisitor.visit(Types.java:3214)
        at com.sun.tools.javac.code.Types.upperBound(Types.java:95)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2968)
        at com.sun.tools.javac.code.Types.adapt(Types.java:2998)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2959)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2968)
        at com.sun.tools.javac.code.Types.adapt(Types.java:2998)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2959)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2968)
        at com.sun.tools.javac.code.Types.adapt(Types.java:2998)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2959)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2968)
        at com.sun.tools.javac.code.Types.adapt(Types.java:2998)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2959)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2968)
        at com.sun.tools.javac.code.Types.adapt(Types.java:2998)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2959)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2968)
        at com.sun.tools.javac.code.Types.adapt(Types.java:2998)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2959)
        at com.sun.tools.javac.code.Types.adaptRecursive(Types.java:2968)

This happens with the following java versoin on Linux:

  : java -fullversion
  java full version "1.6.0_01-b06"

If this can be fixed w/o a test case, that would be wonderful, but otherwise to produce a test case I need to identify which part of the source file is causing this problem. Is there anyway to run javac with some sort of debug flag so that I can figure out which source file is failing to compile? I think that is necessary for me to come up with a smaller test case.
Here's a very small test case:

class A<T extends A<?>> {}
class B extends A<A<?>> {}

class Test {
    A<A<?>> t = null;
    B c = (B)t;
}

Comments
SUGGESTED FIX A webrev of this fix is available at the following URL http://sa.sfbay.sun.com/projects/langtools_data/7/6586091
09-10-2008

EVALUATION The problem is in Types.adapt - the goal of this method is to adapt two generic instantiation by 'unifying' their type-variables (if they contain some). E.g. adapt(List<T>, List<String>, emptylist, emptylist) will add the mapping T->String (that is, T is added in the first list, while String is added in the second list). This method is quite complex as, because of wildcards and type-variables, the method should adapt upper/lower bounds of a given type recursively. As a result it might happen that (because of fbounds) adapting two generic types A and B ends up in an endless loop. In this case we have that A<A<?>> and A<A<?>> should adapted (the two types are the same - but we should adapt them nevertheless). 1. adapt(A<A<?>>, A<A<?>>) 2. adapt(A<?>, A<?>) 3. adapt(?, ?) 3b. adapt(ub(?), ub(?)) 3c. adapt(ub(T), ub(T)) 4. adapt(A<?>, A<?>) ... ... The solution is to adopt a solution similar to the one xploited by the fix of CR 6207386 - that is, adapt should use an internal cache where to store all the pairs of 'already adapted' types; if a type is encountered twice during the same call to adapt(), adapt should give up as no improvement over the current mapping can be achieved.
09-10-2008

EVALUATION To figure out the file in question, it should be enough to use -verbose.
27-07-2007