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

    Details

    • Subcomponent:
    • CPU:
      generic
    • OS:
      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

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

                Dates

                • Created:
                  Updated: