JDK-8162500 : Receiver annotations of inner classes of local classes not found at runtime
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang:reflect
  • Affected Version: 8,9
  • Priority: P3
  • Status: Open
  • Resolution: Unresolved
  • Submitted: 2016-07-25
  • Updated: 2017-04-21
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 :  
Relates :  
Relates :  
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));
    }
}