类级别注释的定义类加载器是否始终是该类的初始类加载器的父级?

Spa*_*ker 11 java classloader

假设如下:

@SomeAnnotation
public interface Foo {
}
Run Code Online (Sandbox Code Playgroud)

我想知道是否始终如此定义的类加载器SomeAnnotation等于或者是启动类加载器的父类Foo.

我已阅读JVMS v8第5.3节.但我不确定这里适用的是什么.第5.3.4节讨论了加载约束,但它们似乎不适用于注释.

我问的问题是因为这样的代码:

    Class<?> fooClass = //will in some way obtain a reference to class Foo
    fooClass.getAnnotation(SomeAnnotation.class);
Run Code Online (Sandbox Code Playgroud)

在不同的类加载器存在的情况下会失败.我知道我可以使用getAnnotations并在结果数组中搜索类名等于的名称的元素SomeAnnotation.但我想知道以下是否也会有效:

    Class<?> fooClass = //will in some way obtain a reference to class Foo
    fooClass.getAnnotation((Class<? extends Annotation>) fooClass
            .getClassLoader().loadClass(SomeAnnotation.class.getName()));
Run Code Online (Sandbox Code Playgroud)

ant*_*tix 8

简短的回答:没有

答案很长.

RetentionPolicy.RUNTIME注释仅可通过反射API进行发现.这样做是为了确保注释和带注释的代码之间的松散耦合.根据此错误报告,getAnnotations()必须跳过未知的注释,这意味着可以使用类加载器无法识别的注释.这里讨论的真实Java代码的行为验证了这个假设.

这种行为有两个含义:

  1. 所有未识别的注释(例如不在类路径中的注释)变得"不可见"
  2. 为了揭示它们,该类必须由可以访问类型和注释的不同类加载器完全重新加载.

例如,如果somepkg.SomeAnnotationsomeClass加载时不在类路径中,则不起作用:

Class<?> someClass = ....
URL [] classPathWithAnnotations = ....

ClassLoader cl = new URLClassLoader(classPathWithAnnotations);
Annotation a = someClass.getAnnotation(cl.loadClass("somepkg.SomeAnnotation"));
// a will be null
Run Code Online (Sandbox Code Playgroud)

但这会:

Class<?> someClass = ....
URL [] classPathWithSomeClassAndAnnotations = ....

ClassLoader cl = new URLClassLoader(classPathWithSomeClassAndAnnotations, null);
Annotation a = cl.loadClass(someClass.getName()).getAnnotation(cl.loadClass("somepkg.SomeAnnotation"));
Run Code Online (Sandbox Code Playgroud)