96 votes

Pourquoi une annotation manquante ne provoque-t-elle pas une exception ClassNotFoundException au moment de l'exécution?

Considérons le code suivant:

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

La compilation et l'exécution fonctionne comme prévu:

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

Mais considérez ceci:

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

Je l'ai attendu pour lancer un ClassNotFoundException, depuis @A est manquant. Mais au lieu de cela, il silencieusement gouttes de l'annotation.

Ce comportement est-il documenté dans le JLS quelque part, ou est-ce un caprice de Sun JVM? Quelle est la justification?

Il paraît commode pour des choses comme l' javax.annotation.Nonnull (ce qui semble comme il aurait été @Retention(CLASS) tout de même), mais pour beaucoup d'autres annotations, il semble que cela pourrait provoquer diverses mauvaises choses de se produire lors de l'exécution.

95voto

jarnbjo Points 18238

Dans la première publiques des ébauches pour la JSR-175 (annotations), il a été examiné si le compilateur et l'exécution doit ignorer inconnu annotations, afin de fournir un couplage lâche entre l'utilisation et de la déclaration des annotations. Un exemple est l'utilisation de serveurs d'applications spécifiques annotations sur fr EJB pour contrôler la configuration de déploiement. Si le même bean devrait être déployé sur un serveur d'application différent, il aurait été plus pratique si l'exécution a tout simplement ignoré l'inconnu annotations au lieu de déclencher une NoClassDefFoundError.

Même si la formulation est un peu vague, je suppose que le comportement que vous voyez est spécifié dans JLS 13.5.7: "... la suppression des annotations n'a aucun effet sur le bon de liaison des représentations binaires des programmes dans le langage de programmation Java." Je interpréter cela comme si les annotations sont supprimés (non disponible au moment de l'exécution), le programme doit encore de lien et de l'exécuter et que cela implique que l'inconnu annotations sont tout simplement ignorés lors de l'accès par le biais de la réflexion.

La première version de Sun JDK 5 n'a pas été mis en oeuvre correctement, mais il a été fixé dans 1.5.0_06. Vous pouvez trouver le bug 6322301 dans la base de données de bogues, mais il ne pointe pas aux spécifications sauf affirmant que "selon la JSR-175 spec lead, inconnu annotations doivent être ignorés par getAnnotations".

35voto

Guillaume Points 6131

Citant le JLS:

9.6.1.2 de Rétention , les Annotations peuvent être présents uniquement dans le code source, ou ils peuvent être présents sous la forme binaire d'une classe ou d'interface. Une annotation qui est présent dans le fichier binaire peut ou peuvent ne pas être disponibles au moment de l'exécution par la réflexion des bibliothèques de Java la plate-forme.

Le type d'annotation annotation.La rétention est utilisé pour choisir parmi les possibilités ci-dessus. Si un annotation correspond à un type T, et T est un (méta-)annotation m correspond à l'annotation.De rétention, alors:

  • Si m est un élément dont la valeur est d'annotation.RetentionPolicy.SOURCE, puis un compilateur Java doit veiller à ce que une n'est pas présent dans le fichier binaire représentation de la classe ou interface dans laquelle un apparaît.
  • Si m est un élément dont la valeur est annotation.RetentionPolicy.CLASS ou annotation.RetentionPolicy.EXÉCUTION d'un Compilateur Java doit s'assurer que a est représenté en binaire représentation de la classe ou interface dans laquelle un semble, à moins que m annote une variable locale de la déclaration. Une annotation sur un local la déclaration de la variable n'est jamais conservé dans la représentation binaire.

Si T n'ont pas de (méta-)annotation m qui correspond à annotation.De rétention, puis un Java compilateur doit traiter T comme si elle ne avoir une telle méta-annotation m avec une élément dont la valeur est annotation.RetentionPolicy.CLASS.

Donc RetentionPolicy.RUNTIME assure que l'annotation est compilé dans le binaire, mais une annotation présents dans le binaire ne pas être disponibles au moment de l'exécution

10voto

irreputable Points 25577

si vous avez réellement du code qui lit @A et fait quelque chose avec, le code a une dépendance sur la classe A, et il lancera ClassNotFoundException.

Si ce n'est pas le cas, aucun code ne se préoccupe spécifiquement de @A, alors il est discutable que @A ne compte pas vraiment.

-1voto

neXus Points 418

Les Annotations n'ont aucun effet direct sur le fonctionnement du code, ils annoter.
Cependant, en utilisant @Retention(RetentionPolicy.RUNTIME) les annotations deviennent disponibles au moment de l'exécution.

Maintenant, je pense qu' @Retention n'est pas disponible et donc ignoré. Cela implique que les autres annotations ne sont pas disponibles au moment de l'exécution.
Il n'y a pas d'exception, car les annotations sont ignorés par défaut. Seulement en présence d' @Retention sont-elles à considérer.

Probablement, si vous faites shure @Retention est disponible, il y aura une plainte. (pas sûr à ce sujet)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X