1

I use the following code, in a JDK8 environment :

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Client", namespace = "http://schemas.datacontract.org/2004/07/BLA.BLA.Model.Client", propOrder = {
"birthDate",
"email",
"ip",
"name",
"phone"
})
@Generated(value = "com.sun.tools.internal.xjc.Driver", date = "2016-12-07T07:34:51+04:00", comments = "JAXB RI v2.2.4-2")
public class Client {

@XmlElementRef(name = "BirthDate", namespace = "http://schemas.datacontract.org/2004/07/BLA.BLA.Model.Client", type = JAXBElement.class, required = false)
@Generated(value = "com.sun.tools.internal.xjc.Driver", date = "2016-12-07T07:34:51+04:00", comments = "JAXB RI v2.2.4-2")

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 @XmlElementRef doesn't have the attribute required 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 required and never uses it, or because of something else?

GPI
  • 9,088
  • 2
  • 31
  • 38
glebiuskv
  • 321
  • 4
  • 13
  • @Sotirios-delimanolis I don't think, my question is duplicate. I edited it, to be more clear. – glebiuskv Feb 06 '17 at 15:59
  • What do you mean _don't know about property_? – Sotirios Delimanolis Feb 06 '17 at 16:08
  • I mean, that it is `@XmlElementRef` from 1.6, i don't call this property manually, so there is no place, where this code is called. – glebiuskv Feb 06 '17 at 16:14
  • Why do you think _it is `@XmlElementRef` from 1.6_? – Sotirios Delimanolis Feb 06 '17 at 16:17
  • It is provided by rt.jar, and run under JDK6. I don't use fat-jar in this project, so from where else can it be? – glebiuskv Feb 06 '17 at 16:19
  • Fair enough, reopened. – Sotirios Delimanolis Feb 06 '17 at 16:21
  • 2
    The only explanation I can give is that a newer version of the JAXB API does enter into the classpath in some way to override the default JDK one. But how that happens will likely lie in the details of the Maven build / the produced binary of the application. As a side note to the why the compile target is set to Java 6 : to support minimally Java 6 of course :) – Gimby Feb 06 '17 at 16:32
  • Agreed with @Gimby that something fishy is going on at compile time, because i'd expect it not to compile too. Still, the question is about runtime... – GPI Feb 06 '17 at 17:37

2 Answers2

2

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.

Adding or removing annotations has no effect on the correct linkage of the binary representations of programs in the Java programming language.

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.

Community
  • 1
  • 1
GPI
  • 9,088
  • 2
  • 31
  • 38
2

Think about it this way: if you have a class implementing an interface, it doesn’t harm, if it has more methods than the interface specifies. If you use that class with an older version of the interface having even less methods, it won’t harm either.

In case of annotations, it’s usually even simpler, as the typical Reflection implementations don’t generate a class having all these methods, but generate a proxy whose invocation handler will look up the requested value by looking up the method’s name in a Map containing the values discovered in the class file. So having more keys in that map than ever requested via interface method calls doesn’t harm either.

Holger
  • 285,553
  • 42
  • 434
  • 765