java - 为什么缺少注释不会在运行时导致 ClassNotFoundException?

标签 java annotations

考虑以下代码:

A.java:

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
@interface A{}

C.java:

import java.util.*;

@A public class C {
        public static void main(String[] args){
                System.out.println(Arrays.toString(C.class.getAnnotations()));
        }
}

编译和运行按预期工作:

$ javac *.java
$ java -cp . C
[@A()]

但是再考虑一下:

$ rm A.class
$ java -cp . C
[]

我预计它会抛出 ClassNotFoundException,因为缺少 @A。但相反,它会默默地删除注释。

这种行为是否记录在 JLS 中的某个地方,还是 Sun 的 JVM 的怪癖?这样做的理由是什么?

对于 javax.annotation.Nonnull 之类的东西似乎很方便(无论如何,它似乎应该是 @Retention(CLASS) ),但对于许多其他注释似乎它可能会导致运行时发生各种不好的事情。

最佳答案

在 JSR-175(注解)的早期公共(public)草案中,讨论了编译器和运行时是否应该忽略未知注解,以便在注解的使用和声明之间提供更松散的耦合。一个具体的例子是在 EJB 上使用应用程序服务器特定的注释来控制部署配置。如果同一个 bean 应该部署在不同的应用服务器上,如果运行时简单地忽略未知注解而不是引发 NoClassDefFoundError 会很方便。

即使措辞有点模糊,我假设您看到的行为在 JLS 13.5.7 中指定。 :“......删除注释对Java编程语言中程序的二进制表示的正确链接没有影响。”我将此解释为好像注释已删除(在运行时不可用),程序仍应链接并运行,这意味着在通过反射访问时会简单地忽略未知注释。

Sun 的 JDK 5 的第一个版本没有正确实现这一点,但在 1.5.0_06 中已修复。你可以找到相关的bug 6322301在错误数据库中,但它没有指向任何规范,除了声称“根据 JSR-175 规范引导,getAnnotations 必须忽略未知注释”。

关于java - 为什么缺少注释不会在运行时导致 ClassNotFoundException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3567413/

相关文章:

java - 保持远程 EJB 和 Web 服务的状态

java - Android - 从 url 下载 JSON 文件

java - Optaplanner 列出规划变量

java - 当两个不同的注释具有相同的名称时会发生什么?

java - 在 Java 中创建具有默认值的 Annotation 实例

java - 如何使用 Google App Engine 插件从 WAR 中排除单元测试?

java - 写入 CSV 文件时,之前的字符串将被覆盖

javascript - Eclipse 大纲 View - Eclipse 中可见的 JavaScript 类别?

java - Guice 如何填充带注释的字段

java - 如何使用 Java 注释插入一些样板代码,就像使用 C 宏一样?