RuntimeVisibleAnnotations and RuntimeInvisibleAnnotations - How to access from code? - java

Section 4.7.16 of the JVM specification includes a description of "RuntimeVisibleAnnotations". I am wondering what can cause an attribute to be included in this attributes table, is this only by applying #Retention(RetentionPolicy.RUNTIME) on an attribute? Conversely, for "RuntimeInvisibleAnnotations" (see further in 4.7.17) is this #Retention(RetentionPolicy.CLASS) only or is it also #Retention(RetentionPolicy.SOURCE) ?

Compiling information from the JVM and JLS specifications gives us the following picture:
Annotations meta-annotated with the #Retention whose value is RetentionPolicy.SOURCE must not be present in the binary representation of the class or interface in which they appear, i.e. they are not to be recorded in the class file at all.
Annotations with the RetentionPolicy.CLASS must be represented in the binary representation of the class or interface in which they appear, unless they annotate a local variable declaration. An annotation on a local variable declaration is never retained in the binary representation.
So this is what the RuntimeInvisibleAnnotations attribute is designed for.
They need not be retained by the VM at run time, unless the Java Virtual Machine has been instructed to retain these annotations via some implementation-specific mechanism such as a command line flag.
Annotations with the RetentionPolicy.RUNTIME are to be recorded in the class file by the compiler and must be available at run time via reflection libraries. This is for the RuntimeVisibleAnnotations attribute.

Related

Is it possible to have a Java annotation that doesn't apply to any class, method, field, etc. Just the annotation itself generating code

Are there such things as Java annotations that aren't tied to any class, method, field, etc.?
Like just writing
#MyAnnotation(someParameter=value, ...)
by itself, and it generates code.
It seems like ExecutableType might define what kinds of "elements" an annotation can annotate, but I'm not sure. If that's true, then ExecutableType derives from TypeMirror, one of whose members are NoType. So maybe it's possible? But I cannot find an example of this.
You cannot have a stand-alone annotation in Java.
Annotations can be applied to different things, for example: types, methods, fields, local variables, packages, method parameters and also on annotation definitions.
One annotation that is meant to be used on annotation definitions (therefore it's called a "meta-annotation") is #Target, which you use to indicate on what things the annotation you are defining is allowed to be used. You do this by specifying one or more element types as an argument to the #Target annotation - see the API docs of java.lang.annotation.ElementType.
The Java Language Specification paragraph 9.6.4.1 explains what annotations can be used on in more detail.

Optional dependency on annotation library with runtime retention [duplicate]

Consider the following code:
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()]
But then consider this:
$ rm A.class
$ java -cp . C
[]
I would've expected it to throw a ClassNotFoundException, since #A is missing. But instead, it silently drops the annotation.
Is this behaviour documented in the JLS somewhere, or is it a quirk of Sun's JVM? What's the rationale for it?
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.
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.
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.
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".
Quoting the JLS:
9.6.1.2 Retention Annotations may be present only in the source code, or
they may be present in the binary form
of a class or interface. An annotation
that is present in the binary may or
may not be available at run-time via
the reflective libraries of the Java
platform.
The annotation type
annotation.Retention is used to choose
among the above possibilities. If an
annotation a corresponds to a type T,
and T has a (meta-)annotation m that
corresponds to annotation.Retention,
then:
If m has an element whose value is annotation.RetentionPolicy.SOURCE,
then a Java compiler must ensure that
a is not present in the binary
representation of the class or
interface in which a appears.
If m has an element whose value is annotation.RetentionPolicy.CLASS, or
annotation.RetentionPolicy.RUNTIME a
Java compiler must ensure that a is
represented in the binary
representation of the class or
interface in which a appears, unless m
annotates a local variable
declaration. An annotation on a local
variable declaration is never retained
in the binary representation.
If T does not have a (meta-)annotation
m that corresponds to
annotation.Retention, then a Java
compiler must treat T as if it does
have such a meta-annotation m with an
element whose value is
annotation.RetentionPolicy.CLASS.
So RetentionPolicy.RUNTIME ensures that the annotation is compiled into the binary but an annotation present in the binary doesn't have to be available at runtime
if you actually have code that reads #A and does something with it, the code has a dependency on class A, and it will throw ClassNotFoundException.
if not, i.e. no code cares specificly about #A, then it's arguable that #A doesn't really matter.

Do repeating annotations need a public container?

I noticed a discrepancy between Eclipse's compiler and javac while using repeating annotations. The repeating annotation and its container were in the same package, but the former was declared public, while the latter remained package-private. Eclipse had no problem with the arrangement, even though the repeating annotation was referenced in another package. javac, on the other hand, refused to compile, saying
value() in [container] is defined in an inaccessible class or interface
My question is, which one is correct? I couldn't find any rule about this in the JLS. Does that mean it's open to interpretation? Or is there a bug in one of the compilers?
There is no statement regarding accessibility but the specification makes it clear that it is possible that a repeatable annotation may be restricted to be repeatable at certain locations only, due to the way how the containing annotation has been declared.
JLS §9.6.3
…
T is applicable to at least the same kinds of program element as TC (§9.6.4.1). Specifically, if the kinds of program element where T is applicable are denoted by the set m1, and the kinds of program element where TC is applicable are denoted by the set m2, then each kind in m2 must occur in m1, …
This clause implements the policy that an annotation type may be repeatable on only some of the kinds of program element where it is applicable
This is also backed with an example:
Example 9.6.3-2. Restricting Where Annotations May Repeat
An annotation whose type declaration indicates a target of java.lang.annotation.ElementType.TYPE can appear in at least as many locations as an annotation whose type declaration indicates a target of java.lang.annotation.ElementType.ANNOTATION_TYPE. For example, given the following declarations of repeatable and containing annotation types:
#Target(ElementType.TYPE)
#Repeatable(FooContainer.class)
#interface Foo {}
#Target(ElementType.ANNOTATION_TYPE)
#Interface FooContainer {
Foo[] value();
}
#Foo can appear on any type declaration while #FooContainer can appear on only annotation type declarations. Therefore, the following annotation type declaration is legal:
#Foo #Foo
#interface X {}
while the following interface declaration is illegal:
#Foo #Foo
interface X {}
While this is discussing restrictions imposed by #Target rather than accessibility modifiers, it describes a “spirit” that can be applied to the latter as well. The intention clearly seems to be that a repeatable annotation can only be repeated if the properties of the specified container annotation allow it, otherwise the annotation still may be used, but only with a single occurrence.
It’s not like the properties of a repeatable annotation were capable of overriding the properties of the container annotation type. This is in line with the behavior at all other places; even if there is no reference to the inaccessible annotation type in the source code, compiling the repeated annotation would create a reference in the class file and a class file may not contain symbolic references to inaccessible classes and there shouldn’t be an exception only for container annotations.

When was #interface introduced in java?

I know this #interface element is used to define annotations in Java.
I know annotations were introduced in Java 5.
My questions:
1) how is that element called (formally), and since when
is it recognized by the compiler i.e. when was it introduced?
Is it an annotation or a meta-annotation itself?
2) before Java 8 (e.g. in Java 5 or 6) was there some other element/way
used for defining annotations or had they always been defined that
way ever since their advent in the language?
how is that element called (formally), and since when is it recognized by the compiler i.e. when was it introduced?
An annotation type declaration. This was added in Java 5.
Is it an annotation or a meta-annotation itself?
No, #interface is not an annotation by itself, it's just the keyword interface preceded by an #. It's not a meta-annotation. A meta-annotation is an annotation that can be used on annotation type declarations. The JDK itself has a number of these (for example #RetentionPolicy).
before Java 8 (e.g. in Java 5 or 6) was there some other element/way used for defining annotations
No.
or they had they always been defined that way ever since their advent in the language?
Yes.
Annotations have been added in Java 5 and #interface was always the way to create annotations; there has not been any other mechanism in the past to create annotations.
Why #interface and not a new keyword such as annotation: This was done for backward compatibility. Adding a new keyword means you immediately create a backward compatibility issue, because programs written for the older version might have used the name of the keyword for example as a variable name. Such programs wouldn't compile anymore on the new version. So, when they want to add a new feature to Java, Oracle prefers re-using an existing keyword instead of creating a new one.
That said, new keywords have been added in the course of the evolution of Java, such as enum and assert (which were added in Java 1.4).

How Java linker works?

I want to know how Java linker works. Specifically, in which order it combines classes, interfaces, packages, methods and etc into jvm-executable format. I have found some information here, but there is not so much information about linking order.
There is no such thing as a Java "linker". There is, however, the concept of a classloader which - given an array of java byte codes from "somewhere" - can create an internal representation of a Class which can then be used with new etc.
In this scenario interfaces are just special classes. Methods and fields are available when the class has been loaded.
First of all: methods are always part of a class. Interfaces are basically just special classes, and packages are just a part of the fully qualified name of a class with some impact on visibility and the physical organization of class files.
So the question comes down to: how does a JVM link class files? The JVM spec you linked to says:
The Java programming language allows
an implementation flexibility as to
when linking activities (and, because
of recursion, loading) take place,
provided that the semantics of the
language are respected, that a class
or interface is completely verified
and prepared before it is initialized,
and that errors detected during
linkage are thrown at a point in the
program where some action is taken by
the program that might require linkage
to the class or interface involved in
the error.
For example, an implementation may
choose to resolve each symbolic
reference in a class or interface
individually, only when it is used
(lazy or late resolution), or to
resolve them all at once, for example,
while the class is being verified
(static resolution). This means that
the resolution process may continue,
in some implementations, after a class
or interface has been initialized.
Thus, the question can only be answered for a specific JVM implementation.
Furthermore, it should never make a difference in the behaviour of Java programs, except possibly for the exact point where linking errors result in runtime Error instances being thrown.
Java doesn't do linking the way C does. The principle unit is the class definition. A lot of the matching of a class reference to its definition happens at runtime. So you could compile a class against one version of a library, but provide another version at runtime. If the relevant signatures match, everything will be ok. There's some in-lining of constants at compile time, but that's about it.
As noted previously Java compiler doesn't have a linker. However, JVM has a linking phase, which performed after class loading. JVM spec defines it at best:
Linking a class or interface involves verifying and preparing that
class or interface, its direct superclass, its direct superinterfaces,
and its element type (if it is an array type), if necessary.
Resolution of symbolic references in the class or interface is an
optional part of linking.
This specification allows an implementation flexibility as to when
linking activities (and, because of recursion, loading) take place,
provided that all of the following properties are maintained:
A class or interface is completely loaded before it is linked.
A class or interface is completely verified and prepared before it is
initialized.
Errors detected during linkage are thrown at a point in the program
where some action is taken by the program that might, directly or
indirectly, require linkage to the class or interface involved in the
error.
https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-5.html#jvms-5.4
Linking is one of the three activities performed by ClassLoaders. It includes verification, preparation, and (optionally) resolution.
Verification : It ensures the correctness of .class file i.e. it check whether this file is properly formatted and generated by valid compiler or not. If verification fails, we get run-time exception java.lang.VerifyError.
Preparation : JVM allocates memory for class variables and initializing the memory to default values.
Resolution : It is the process of replacing symbolic references from the type with direct references. It is done by searching into method area to locate the referenced entity.

Categories