Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8203337

5.1.6.2: Local inner class in generic method should be treated as generic

    XMLWordPrintable

Details

    • generic
    • generic

    Description

      A DESCRIPTION OF THE PROBLEM :
      Local inner classes in generic methods should be treated as generic types: casts to them should be unchecked and they should not be allowed to extend Throwable. I suspect this is a problem in the JLS.

      See included examples demonstrating this as a type system loophole: there are no unchecked warnings, yet this causes heap pollution. The first example shows that such a cast should be treated as unchecked, and the second that it's not safe to allow such a local inner class in a generic method to extend Throwable.

      This (and other bugs) comes from this blog post: http://wouter.coekaerts.be/2018/java-type-system-broken

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      compile and run the code

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      unchecked warnings or compilation errors
      ACTUAL -
      heap pollution, ClassCastException

      ---------- BEGIN SOURCE ----------
      public class LocalInnerClass {
        static Object prev;
        static <T> T go(T t) {
          class A extends ArrayList<T> { }
          if (prev == null) { // first execution
            A a = new A();
            a.add(t);
            prev = a;
            return null;
          } else { // second execution
            return ((A) prev).get(0);
          }
        }

        public static void main(String[] args) {
          go(1);
          String s = go(""); // ClassCastException
        }
      }

      public class LocalInnerClassWithException {
        static <T> T go(T in, Object other) {
          class A extends RuntimeException {
            T t;
          }
          if (other != null) { // first execution
            try {
              go(other, null);
            } catch (A a) {
              return a.t; // returns other
            }
            throw new AssertionError(); // unreachable
          } else {
            A a = new A();
            a.t = in;
            throw a;
          }
        }

        public static void main(String[] args) {
          String s = go("", 1); // ClassCastException
        }
      }
      ---------- END SOURCE ----------

      FREQUENCY : always


      Attachments

        Issue Links

          Activity

            People

              dlsmith Dan Smith
              webbuggrp Webbug Group
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

                Created:
                Updated: