为什么缺少注释在运行时不会导致 ClassNotFoundException? [英] Why doesn't a missing annotation cause a ClassNotFoundException at runtime?

查看:25
本文介绍了为什么缺少注释在运行时不会导致 ClassNotFoundException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

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()));
        }
}

编译和运行按预期工作:

Compiling and running works as expected:

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

但是考虑一下:

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

我原以为它会抛出 ClassNotFoundException,因为缺少 @A.但是,它会默默地删除注释.

I would've expected it to throw a ClassNotFoundException, since @A is missing. But instead, it silently drops the annotation.

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

Is this behaviour documented in the JLS somewhere, or is it a quirk of Sun's JVM? What's the rationale for it?

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

It seems convenient for things like javax.annotation.Nonnull (which seems like it should've been @Retention(CLASS) anyway), but for many other annotations it seems like it could cause various bad things to happen at runtime.

推荐答案

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

In the earlier public drafts for JSR-175 (annotations), it was discussed if the compiler and runtime should ignore unknown annotations, to provide a looser coupling between the usage and declaration of annotations. A specific example was the use of applications server specific annotations on an EJB to control the deployment configuration. If the same bean should be deployed on a different application server, it would have been convenient if the runtime simply ignored the unknown annotations instead of raising a NoClassDefFoundError.

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

Even if the wording is a little bit vague, I assume that the behaviour you are seeing is specified in JLS 13.5.7: "... removing annotations has no effect on the correct linkage of the binary representations of programs in the Java programming language." I interpret this as if annotations are removed (not available at runtime), the program should still link and run and that this implies that the unknown annotations are simply ignored when accessed through reflection.

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

The first release of Sun's JDK 5 did not implement this correctly, but it was fixed in 1.5.0_06. You can find the relevant bug 6322301 in the bug database, but it does not point to any specifications except claiming that "according to the JSR-175 spec lead, unknown annotations must be ignored by getAnnotations".

这篇关于为什么缺少注释在运行时不会导致 ClassNotFoundException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆