JDK-8203335 : 15.9.3: Anonymous inner class can have capture type in supertype
  • Type: Bug
  • Component: specification
  • Sub-Component: language
  • Affected Version: 9,10,10.0.1,11
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: generic
  • Submitted: 2018-05-17
  • Updated: 2018-07-09
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
tbd_majorUnresolved
Related Reports
Relates :  
Description
A DESCRIPTION OF THE PROBLEM :
This problem is about anonymous inner classes extending inner classes nested in generic classes when the outer instance has a wildcard in its type. It creates a class whose super class has a capture type as type parameter. That causes multiple problems.
For one, this can cause heap pollution (without unchecked warnings).
This also makes javac write out an incorrect type signature, causing a java.lang.reflect.GenericSignatureFormatError when using Class.getGenericSuperclass().

I originally wrote about this problem in this blog post: http://wouter.coekaerts.be/2018/java-type-system-broken


---------- BEGIN SOURCE ----------
public class CaptureInSuperClass {
  static class Box<A> {
    A a;
    Box(A a) { this.a = a; }

    class Inner {
      void setA(A newA) {
        a = newA;
      }

      A getA() {
        return a;
      }
    }
  }

  static Object prev;
  public static void main(String[] args) {
    Box<String> stringBox = new Box<>("1");
    for (Box<?> box : List.of(stringBox, new Box<>(1))) {
      box.new Inner() {{
        if (prev == null) prev = this;
        else this.getClass().cast(prev).setA(this.getA());
      }};
    }

    // ClassCastException
    String s = stringBox.a;

    // GenericSignatureFormatError
    ((Box<?>)stringBox).new Inner(){}.getClass().getGenericSuperclass();
  }
}
---------- END SOURCE ----------

FREQUENCY : always



Comments
Underlying problem: enclosing instance expressions allow non-denoteable types to leak into the superclass type. We prohibit this when diamond inference determines the supertype (15.9.3), but not here. This is a good illustration of the issues we would face if we ever decided to relax the prohibition against capture variables in anonymous class supertypes.
17-05-2018

There are 2 issues observerd here 1. CCE on "String s = stringBox.a; " -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/java CaptureInSuperClass Exception in thread "main" java.lang.ClassCastException: java.base/java.lang.Integer cannot be cast to java.base/java.lang.String at CaptureInSuperClass.main(CaptureInSuperClass.java:29) 2. GSFE on "((Box<?>)stringBox).new Inner(){}.getClass().getGenericSuperclass(); " -sh-4.2$ /scratch/fairoz/JAVA/jdk11/jdk-11-ea+13/bin/java CaptureInSuperClass Exception in thread "main" java.lang.reflect.GenericSignatureFormatError: Signature Parse error: ; expected in signature of type variable named Remaining input: <captured wildcard>;>.Inner; at java.base/sun.reflect.generics.parser.SignatureParser.error(SignatureParser.java:124) at java.base/sun.reflect.generics.parser.SignatureParser.parseTypeVariableSignature(SignatureParser.java:434) at java.base/sun.reflect.generics.parser.SignatureParser.parseFieldTypeSignature(SignatureParser.java:285) at java.base/sun.reflect.generics.parser.SignatureParser.parseFieldTypeSignature(SignatureParser.java:277) at java.base/sun.reflect.generics.parser.SignatureParser.parseTypeArgument(SignatureParser.java:420) at java.base/sun.reflect.generics.parser.SignatureParser.parseTypeArguments(SignatureParser.java:380) at java.base/sun.reflect.generics.parser.SignatureParser.parsePackageNameAndSimpleClassTypeSignature(SignatureParser.java:335) at java.base/sun.reflect.generics.parser.SignatureParser.parseClassTypeSignature(SignatureParser.java:304) at java.base/sun.reflect.generics.parser.SignatureParser.parseClassSignature(SignatureParser.java:213) at java.base/sun.reflect.generics.parser.SignatureParser.parseClassSig(SignatureParser.java:156) at java.base/sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:57) at java.base/sun.reflect.generics.repository.ClassRepository.parse(ClassRepository.java:41) at java.base/sun.reflect.generics.repository.AbstractRepository.<init>(AbstractRepository.java:74) at java.base/sun.reflect.generics.repository.GenericDeclRepository.<init>(GenericDeclRepository.java:49) at java.base/sun.reflect.generics.repository.ClassRepository.<init>(ClassRepository.java:53) at java.base/sun.reflect.generics.repository.ClassRepository.make(ClassRepository.java:70) at java.base/java.lang.Class.getGenericInfo(Class.java:3004) at java.base/java.lang.Class.getGenericSuperclass(Class.java:914) at CaptureInSuperClass.main(CaptureInSuperClass.java:32)
17-05-2018