JDK-4982096 : Object.getClass() leads to type system loophole
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 5.0
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_8
  • CPU: generic
  • Submitted: 2004-01-22
  • Updated: 2017-05-16
  • Resolved: 2004-04-16
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.
Other
5.0 b48Fixed
Related Reports
Relates :  
Description
There is a loophole in the type system that is present because
we made getSuperclass() return a Class with an argument of a generic
type.  This comes about because of a cast() operation we recently
added to class Class:

2384     /**
2385      * Casts an object to the class or interface represented
2386      * by this <tt>Class</tt> object.
2387      *
2388      * @param obj the object to be cast
2389      * @return the object after casting, or null if obj is null
2390      *
2391      * @throws ClassCastException if the object is not
2392      * null and is not assignable to the type T.
2393      *
2394      * @since 1.5
2395      */
2396     public T cast(Object obj) {
2397         if (obj != null && !isInstance(obj))
2398             throw new ClassCastException();
2399         return (T) obj;
2400     }

The loophole works like this:

    class A extends List<Integer> {}

    List<String> ls = new List<String>();
    List<Integer> li = 
                  A.class.getSuperclass() // Class<List<Integer>>
                  .cast(ls);
    li.add(1);
    String s = ls.get() // BANG!

We can either remove the cast() operator (which would be a shame - it
is really useful - see 4881275) or make the class type returned by
A.class.getSuperclass be Class<List> instead of Class<List<Integer>>.


----------------
See Evaluation section for corrected type loophole snippet.

###@###.### 2004-04-02


Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger-beta2 FIXED IN: tiger-beta2 INTEGRATED IN: tiger-b48 tiger-beta2
14-06-2004

PUBLIC COMMENTS ...
10-06-2004

EVALUATION Actually, there is no compiler magic in getSuperclass() that would lead to a type loophole. If you try the example in the description you'll see why. However, there IS a problem due to the interaction of getClass() and cast(), and due to the interaction of class literals of generic types and cast(). We can fix these by requiring that all values of type Class<> generated by these techniques erase the argument type. A spec based on this scheme is awaiting CCC approval. ###@###.### 2004-02-27 Here's the real type loophole in action: List<String> ls = new ArrayList<String>(); List<Integer> li = new ArrayList<Integer>(); li = li.getClass().cast(ls); // no unchecked assignment warning li.add(1); String s = ls.get(0); // BANG! ###@###.### 2004-04-02 Parameterized class literals are already disallowed by the grammar. We should also disallow parameterized types from being used in instanceof expressions, since there's nothing that can be done with the type arguments at run time. ###@###.### 2004-04-02
02-04-2004