United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-5009937 : hiding versus generics versus binary compatibility

Details
Type:
Bug
Submit Date:
2004-03-09
Status:
Closed
Updated Date:
2010-03-02
Project Name:
JDK
Resolved Date:
2011-05-17
Component:
tools
OS:
solaris_8
Sub-Component:
javac
CPU:
generic
Priority:
P3
Resolution:
Fixed
Affected Versions:
5.0
Fixed Versions:

Related Reports
Duplicate:
Relates:
Relates:

Sub Tasks

Description
The following illustrates that the binary compatibility rules conflict
with generics.  The method resolved at compile time and at runtime are
different, resulting in a runtime call to the wrong method.

Date: Wed, 25 Feb 2004 14:15:59 -0800
From: <###@###.###>
Subject: Method isn't hidden, but acts like it is at runtime
To: ###@###.###
Cc: ###@###.###

import java.util.*;

import static java.lang.System.out;

public class T2 {

    public static void main(String[] args) {
        Collection c = T2a.m(new ArrayList<String>());  // => "T2a.m"
    }

    static Collection m(List<String> p) {
        out.println("T2.m");
        return null;
    }
}


class T2a extends T2 {

    static Collection m(List<Number> p) {
        out.println("T2a.m");
        return null;
    }
}

                                    

Comments
SUGGESTED FIX

the code is below
                                     
2008-02-29
SUGGESTED FIX

see http://sa.sfbay.sun.com/projects/langtools_data/7/5009937/
                                     
2008-02-29
SUGGESTED FIX

I also fixed a defect in checkCompatibleConcreters. The new implementation fixes a bug that I discovered involving classes inheriting two methods with the same signature, as javac was able to detect the error in this situation:

class A<X> {
    void m(X x) {}
    void m(Integer i) {}
}

class C extends A<Integer> {}

But NOT in this slightly trickier one:

class A<X> {
    void m(X x) {}
}

class B<T> extends A<T> {
    void m(Integer i) {}
}

class C extends B<Integer> {}

since the two clashing methods come from different classes and there was a bug in the way in which javac walked the inheritance tree.
                                     
2008-02-29
EVALUATION

As previous evaluations have suggested, this bug is due to the fact that the subclass T2a is inheriting the static member T2.m() whose signature conflicts with its static member T2a.m() (argument types are different).

JLS 8.4.8.3 state that:

"It is a compile time error if a type declaration T has a member method m1 and there exists a method m2 declared in T or a supertype of T such that all of the following conditions hold:

* m1 and m2 have the same name.
* m2 is accessible from T.
* The signature of m1 is not a subsignature (??8.4.2) of the signature of m2.
* m1 or some method m1 overrides (directly or indirectly) has the same erasure as m2 or some method m2 overrides (directly or indirectly). "

The last condition is the one that matters here. That condition ensures that type erasure can never generate two methods with the same signature in the same class (which would be inconsistent).

A good point where to insert this check is in Check.checkOverride. However special care is required since we must be sure to not generate inappropriate errors (e.g. we must skip constructors, non inherited members, etc.). 

This new implementation of checkOverrides has the advantage of detecting errors earlier. In fact, in a scenario in which two non-static, non overriding methods are inherited by a given class, javac used to be able to report the error only after having applied type-erasure on method symbols and generated bridges for generic inherited methods (which is the last step of the compiler pipeline before code generation). With this new implementation javac is able to detect the error while attributing the class (and this is the correct behaviour since the class is not well-formed wrt to the JLS 8.4.8.3).
                                     
2008-02-29
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
dragon
mustang


                                     
2004-09-07
EVALUATION

Two methods in same hierarchy, accessible, same name and erasure but
different signature.  This is a compile time error (at the definition of T2a).

###@###.### 2004-07-09

This is therefore a compiler bug.

###@###.### 2004-07-09
                                     
2004-07-09



Hardware and Software, Engineered to Work Together