type retentionpolicy notacion crear anotación annotation java annotations

java - retentionpolicy - ¿Por qué una anotación faltante no causa una ClassNotFoundException en tiempo de ejecución?



java lang annotation (4)

Considera el siguiente código:

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

Compilar y ejecutar funciona como se espera:

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

Pero luego considera esto:

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

Hubiera esperado lanzar una @A ClassNotFoundException , ya que falta @A . Pero, en cambio, deja caer la anotación en silencio.

¿Este comportamiento está documentado en el JLS en alguna parte, o es una peculiaridad de la JVM de Sun? ¿Cuál es la razón para esto?

Parece conveniente para cosas como javax.annotation.Nonnull (que parece que debería haber sido @Retention(CLASS) todos modos), pero para muchas otras anotaciones parece que podría causar varias cosas malas en el tiempo de ejecución.


Citando el JLS:

9.6.1.2 Las anotaciones de retención pueden estar presentes solo en el código fuente, o pueden estar presentes en la forma binaria de una clase o interfaz. Una anotación que está presente en el binario puede o no estar disponible en tiempo de ejecución a través de las bibliotecas reflexivas de la plataforma Java.

Anotación del tipo de anotación. La retención se usa para elegir entre las posibilidades anteriores. Si una anotación a corresponde a un tipo T, y T tiene una (meta) anotación m que corresponde a la anotación. Retención, entonces:

  • Si m tiene un elemento cuyo valor es anotación. RetentionPolicy.SOURCE, un compilador de Java debe asegurarse de que a no está presente en la representación binaria de la clase o interfaz en la que aparece a.
  • Si m tiene un elemento cuyo valor es annotation.RetentionPolicy.CLASS o annotation.RetentionPolicy.RUNTIME, un compilador de Java debe asegurarse de que a se representa en la representación binaria de la clase o interfaz en la que a aparece, a menos que m anote una declaración de variable local . Una anotación en una declaración de variable local nunca se retiene en la representación binaria.

Si T no tiene una (meta) anotación m que corresponda a la anotación. Retención, entonces un compilador de Java debe tratar a T como si tuviera una metaanotación de este tipo m con un elemento cuyo valor es la anotación. RetentionPolicy.CLASS.

Entonces RetentionPolicy.RUNTIME asegura que la anotación se compila en el binario, pero una anotación presente en el binario no tiene que estar disponible en el tiempo de ejecución


En los borradores públicos anteriores para JSR-175 (anotaciones), se discutió si el compilador y el tiempo de ejecución deben ignorar las anotaciones desconocidas, para proporcionar un acoplamiento más flexible entre el uso y la declaración de anotaciones. Un ejemplo específico fue el uso de anotaciones específicas del servidor de aplicaciones en un EJB para controlar la configuración de implementación. Si el mismo bean se implementara en un servidor de aplicaciones diferente, hubiera sido conveniente si el tiempo de ejecución simplemente ignoró las anotaciones desconocidas en lugar de generar un NoClassDefFoundError.

Incluso si la redacción es un poco vaga, supongo que el comportamiento que está viendo se especifica en JLS 13.5.7: "... eliminar anotaciones no tiene ningún efecto sobre el enlace correcto de las representaciones binarias de los programas en el lenguaje de programación Java " Interpreto esto como si se eliminaran las anotaciones (no disponible en tiempo de ejecución), el programa aún debe vincularse y ejecutarse, y eso implica que las anotaciones desconocidas simplemente se ignoran cuando se accede a ellas a través de la reflexión.

La primera versión de JDK 5 de Sun no implementó esto correctamente, pero se corrigió en 1.5.0_06. Puede encontrar el error relevante 6322301 en la base de datos de errores, pero no apunta a ninguna especificación, excepto que alega que "de acuerdo con la especificación JSR-175, las anotaciones desconocidas deben ser ignoradas por getAnnotations".


Las anotaciones no tienen un efecto directo en el funcionamiento del código que anotan.
Sin embargo, al usar @Retention(RetentionPolicy.RUNTIME) las anotaciones estarán disponibles en tiempo de ejecución.

Ahora, supongo que @Retention no está disponible y, por lo tanto, se ignora. Esto implica que las otras anotaciones no están disponibles en tiempo de ejecución.
No hay excepción porque las anotaciones se ignoran por defecto. Solo en presencia de @Retention se consideran.

Probablemente si haces que @Retention esté disponible, habrá una queja. (no estoy seguro de esto)


si realmente tiene un código que lee @A y hace algo con él, el código tiene una dependencia en la clase A, y lanzará ClassNotFoundException.

si no, es decir, ningún código se preocupa específicamente por @A, entonces es discutible que @A en realidad no importe.