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

Receiver annotations of inner classes of local classes not found at runtime

    Details

    • Type: Bug
    • Status: Open
    • Priority: P3
    • Resolution: Unresolved
    • Affects Version/s: 8, 9
    • Fix Version/s: tbd_major
    • Component/s: core-libs
    • Labels:
      None

      Description

      Receiver parameter annotations of inner classes of local classes (but not inner classes of static member classes) are not found at runtime.

      For annotated receivers of inner classes of both static member classes and local classes in static methods, javac correctly generates runtime annotations. However, if they are queried at runtime using Executable.getAnnotatedReceiverType().getAnnotations, the annotations from inner classes of local classes are not returned. Test follows:

      /*
       * Copyright 2016 Google Inc. All Rights Reserved.
       * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       *
       * This code is free software; you can redistribute it and/or modify it
       * under the terms of the GNU General Public License version 2 only, as
       * published by the Free Software Foundation.
       *
       * This code is distributed in the hope that it will be useful, but WITHOUT
       * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
       * version 2 for more details (a copy is included in the LICENSE file that
       * accompanied this code).
       *
       * You should have received a copy of the GNU General Public License version
       * 2 along with this work; if not, write to the Free Software Foundation,
       * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       *
       * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       * or visit www.oracle.com if you need additional information or have any
       * questions.
       */

      import java.lang.annotation.Annotation;
      import java.lang.annotation.ElementType;
      import java.lang.annotation.Retention;
      import java.lang.annotation.RetentionPolicy;
      import java.lang.annotation.Target;
      import java.lang.reflect.AnnotatedType;
      import java.lang.reflect.Constructor;
      import java.lang.reflect.Executable;
      import java.util.Arrays;

      /**
       * Receiver parameter annotations of inner classes of local classes not
       * found at runtime.
       */
      public class ReceiverAnnotation {

          @Retention(RetentionPolicy.RUNTIME)
          @Target({ ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
          public @interface Anno {}

          static class Member {
              abstract class Inner {
                  Inner(@Anno Member Member.this) { m(); }
                  abstract void myMethod(@Anno Inner this);
              }
              void m() {}
          }

          public static void main(String[] args) throws Throwable {
              class Local {
                  abstract class Inner {
                      Inner(@Anno Local Local.this) { m(); }
                      abstract void myMethod(@Anno Inner this);
                  }
                  void m() {}
              }

              int fails = 0;
              Class<?>[] clazzes = { Member.Inner.class, Local.Inner.class };
              for (Class<?> clazz : clazzes) {
                  try {
                      assertReceiverAnnotated(
                          clazz.getDeclaredMethod("myMethod"));
                  } catch (Throwable t) {
                      System.err.println(clazz.getName());
                      t.printStackTrace();
                      fails++;
                  }
                  try {
                      assertReceiverAnnotated(
                          clazz.getDeclaredConstructor(clazz.getEnclosingClass()));
                  } catch (Throwable t) {
                      System.err.println(clazz.getName());
                      t.printStackTrace();
                      fails++;
                  }
              }

              if (fails > 0) throw new AssertionError();
          }

          static void assertReceiverAnnotated(Executable ex) {
              AnnotatedType type = ex.getAnnotatedReceiverType();
              String expected = "[@" + Anno.class.getName() + "()]";
              String actual = Arrays.toString(type.getAnnotations());
              if (!expected.equals(actual))
                  throw new AssertionError(
                      String.format("expected: %s, actual: %s",
                                    expected, actual));
          }
      }

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                dlsmith Dan Smith
                Reporter:
                martin Martin Buchholz
              • Votes:
                0 Vote for this issue
                Watchers:
                4 Start watching this issue

                Dates

                • Created:
                  Updated: