glebiuskv glebiuskv - 4 years ago 94
Java Question

Use of a new annotation attribute in a pre-existing compiled context

I use the following code, in a JDK8 environment :

@XmlType(name = "Client", namespace = "", propOrder = {
@Generated(value = "", date = "2016-12-07T07:34:51+04:00", comments = "JAXB RI v2.2.4-2")
public class Client {

@XmlElementRef(name = "BirthDate", namespace = "", type = JAXBElement.class, required = false)

This code is used in an application that compiled under JDK8 with maven`s builder target set to 1.6 and run under JDK6. (Don't ask me why :( )

I am interested in knowing how it works? The property
doesn't have the attribute
in JDK6's version and it can't be built with it.

PS. I don't ask, why i can compile code. I'm interested why i can run it. Is it because of some annotation specific semantics, because my code doesn't know of this property
and never uses it, or because of something else?

Answer Source

This is a tentative answer, that I do not claim is totally accurate, but seems a reasonnable take on this issue.

It is stated in the JLS, in the binary compatibility (emphasis mine):

13.5.7. Evolution of Annotation Types

Annotation types behave exactly like any other interface. Adding or removing an element from an annotation type is analogous to adding or removing a method. There are important considerations governing other changes to annotation types, but these have no effect on the linkage of binaries by the Java Virtual Machine. Rather, such changes affect the behavior of reflective APIs that manipulate annotations. The documentation of these APIs specifies their behavior when various changes are made to the underlying annotation types.


If we refer to what is said of interfaces :

13.5.3. Interface Members

Adding a method to an interface does not break compatibility with pre-existing binaries.

My understanding is that the requiered "element" of the @XmlElementRef is represented internally as an interface's method.

So you can reason about its compatibility with previous JDKs just as you would of any other interface. If you use a given method of a given interface, you need it in the interface declaration for your code to compile. This is why your code does not compile on JAXB versions priori to 2.2 (See this : JDK6 ships with JAXB 2.1.10).

However, if you have code that is already compiled (a "pre-built binary"), as long as nothing ever needs to access the said method (directly, through reflection), then it's fine for the runtime for this method not to exist.
