JDK-7024568 : Very long method resolution causing OOM error
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 6
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: unknown
  • Submitted: 2011-03-04
  • Updated: 2011-09-14
  • Resolved: 2011-04-20
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 6 JDK 7
6u30Fixed 7 b134Fixed
Related Reports
Relates :  
Description
Javac hangs while compiling the following program:


package pkg196134;

public class Main {

    public static void main(String[] args) {
        Obj o = null;
        o.test(0, 0, 0, 0, 0, 0, 0, 0, undefined);
    }
}

interface Test {
    public void test(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, String str);
    public void test(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, long l);
}

interface Obj extends Test, A, B, C, D, E {}
interface A extends Test {}
interface B extends A, Test {}
interface C extends A, B, Test {}
interface D extends A, B, C, Test {}
interface E extends A, B, C, D, Test {}


Compilation eventually fails with the following stack trace:

The system is out of resources.
Consult the following stack trace for details.
java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOfRange(Arrays.java:2694)
	at java.lang.String.<init>(String.java:234)
	at java.lang.StringBuilder.toString(StringBuilder.java:405)
	at com.sun.tools.javac.util.JCDiagnostic$Factory.qualify(JCDiagnostic.java:234)
	at com.sun.tools.javac.util.JCDiagnostic$Factory.create(JCDiagnostic.java:230)
	at com.sun.tools.javac.util.JCDiagnostic$Factory.fragment(JCDiagnostic.java:200)
	at com.sun.tools.javac.comp.Resolve$InapplicableMethodException.setMessage(Resolve.java:496)
	at com.sun.tools.javac.comp.Resolve.checkRawArgumentsAcceptable(Resolve.java:444)
	at com.sun.tools.javac.comp.Resolve.rawInstantiate(Resolve.java:389)
	at com.sun.tools.javac.comp.Resolve.instantiate(Resolve.java:405)
	at com.sun.tools.javac.comp.Resolve.signatureMoreSpecific(Resolve.java:820)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:727)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:803)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:803)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:803)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:803)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:803)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:803)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:803)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)
	at com.sun.tools.javac.comp.Resolve.mostSpecific(Resolve.java:802)

Comments
SUGGESTED FIX A webrev of this fix is available at the following URL: http://hg.openjdk.java.net/jdk7/tl/langtools/rev/74f0c05c51eb
07-03-2011

EVALUATION Method resolution scans all supertypes of a given 'site' looking for a potentially applicable method. The problem is that the inheritance graph in this example: interface Obj extends Test, A, B, C, D, E {} interface A extends Test {} interface B extends A, Test {} interface C extends B, A, Test {} ... Note that each new interface extends all existing interfaces. Since the 'site' we are starting with has type 'Obj', we need to scan all supertypes of Obj: Obj -> { Test, A, B, C, D, E } then for each type in the above list we should scan all supertypes: Test -> {} A -> { Test } B -> {Test, A } C -> { Test, A, B } ... then, for each type in the above lists we should again determine all supertypes and look for potential candidates... this lead to a combinatorial explosion of checks - which is made worse by the fact that each time javac comes up with a pair of candidates, they are ambiguous (because the last argument in the method call is erroneous, so both methods are applicable but neither is most specific). This means that javac ends up constructing bigger and bigger tree of AmbiguityErrors (because both methods in Test are seen more than once). The solution is to truncate recursion when we are scanning a supertype that has already been scanned. For example: Step 1: Obj -> { Test, A, B, C, D, E } Step 2: Test -> {} A -> { Test } -> {} //Test already scanned B -> {Test, A } -> {} //Test, A already scanned C -> { Test, A, B } -> {} //Test, A,B already scanned ... That is, during the second (recursive) step we are already able to determine that all candidates have already been retrieved.
04-03-2011