【问题标题】:Is the defining classloader of a class level annotation always a parent of the initiating classloader of that class?类级别注释的定义类加载器是否总是该类的启动类加载器的父级?
【发布时间】:2014-05-07 02:58:07
【问题描述】:

假设如下:

@SomeAnnotation
public interface Foo {
}

我想知道SomeAnnotation 的定义类加载器是否总是等于Foo 的启动类加载器的父级。

我已阅读JVMS v8 section 5.3。但我不确定这里适用什么。 5.3.4 节讲了加载约束,但是好像没有申请注解。

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

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

在存在不同的类加载器时会失败。我知道我可以使用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()));

【问题讨论】:

    标签: java classloader


    【解决方案1】:

    简短的回答:没有

    长答案。

    RetentionPolicy.RUNTIME 注释仅可通过反射 API 进行发现。这样做是为了确保注释和注释代码之间的松散耦合。根据this bug reportgetAnnotations() 必须跳过未知注释,这意味着可以有类加载器无法识别的注释。 here 讨论的真实 Java 代码的行为验证了这一假设。

    这种行为有两个含义:

    1. 所有无法识别的注释(例如不在类路径中的注释)都将变为“不可见”
    2. 为了显示它们,该类必须完全由另一个可以访问类型和注释的类加载器重新加载。

    例如,如果 somepkg.SomeAnnotation 在加载 someClass 时不在类路径中,这将不起作用:

    Class<?> someClass = ....
    URL [] classPathWithAnnotations = ....
    
    ClassLoader cl = new URLClassLoader(classPathWithAnnotations);
    Annotation a = someClass.getAnnotation(cl.loadClass("somepkg.SomeAnnotation"));
    // a will be null
    

    但这会:

    Class<?> someClass = ....
    URL [] classPathWithSomeClassAndAnnotations = ....
    
    ClassLoader cl = new URLClassLoader(classPathWithSomeClassAndAnnotations, null);
    Annotation a = cl.loadClass(someClass.getName()).getAnnotation(cl.loadClass("somepkg.SomeAnnotation"));
    

    【讨论】:

    • 感谢您的出色回答。当您发布它时,我已经亲自参与了您的回答。我注意到 Oracle JVM 在请求注释时使用了AnnotationParser。因此,由于注解是惰性加载的,因此在 JVMS 或 JLS 中无需额外注意它们。
    • 谢谢。它帮助我了解我的情况出了什么问题。很好的解释。
    猜你喜欢
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-11
    相关资源
    最近更新 更多