Regression in JDK8 build 78: javac complains about missing Class#isAnnotationPresent
Joe Darcy
joe.darcy at oracle.com
Fri Mar 1 10:41:47 PST 2013
Hello Uwe,
On 3/1/2013 12:44 AM, Uwe Schindler wrote:
>
> Hi Joe,
>
> thanks for the response! I fully understand the reasoning behind your
> first response to my original to the mailing list. Actually there are
> 3 settings that can be used to make older code compile against newer
> JDKs. Most projects unfortunately use “-source” + “-target” at the
> same time, although only “-target” is needed to create class files.
> But javac dictates that -source must also be –target (it otherwise
> complains).
>
The actual constraint from javac is a bit different: the basic check is
that -target has to be as least as large as -source. A combination like
-source 6 / -target 8 would be acceptable.
The javac man page has some details and I've written a related blog
entry at:
"Source, target, class file version decoder ring,"
https://blogs.oracle.com/darcy/entry/source_target_class_file_version
> So the only workaround is to use a bootclasspath and give both options
> to be identical and corresponding to the bootclasspath. But if you try
> to set this up, you already have the older JDK installed, so you can
> also compile your code against the older JDK J.
>
> I understand that this is the recommended solution as suggested by
> Oracle. Unfortunately to set this up, developers and people who want
> to compile open source projects have to take care of additionally
> installing an old JDK version (or at least somewhere download the old
> rt.jar). If rt.jar reference editions would be available in the public
> (just to be used as bootclasspath), e.g. as artifacts on Maven
> Central, the setup would be easy: Maven/Ivy could download rt.jar as a
> dependency and compile against it with any JDK installed on the
> computer of the user. If this would work, we would all be happy and
> your recommended approach would be easy to set up!
>
> But this is not the case: So open source project generally use the
> following approach:
>
> -They use –target and –source with an older JDK version. This allows
> them to produce class files that can be read with older versions. This
> always worked until today.
>
> -While releasing the project they are using the “official JDK version”
> to build the artifacts (and also in nightly builds/continuous
> testing), so they can easily detect calls to APIs only available in
> newer JDKs. The developers (often people working on Mac OSX, where
> e.g. no JDK 1.5 and soon no JDK 1.6 is available anymore) can then
> easily develop the code using newer JDKs, but continuous testing would
> ensure that the code is actually compatible. For this
> “-source/-target” would not be needed.
>
> -“-source/-target” is used to make the build somehow “reproducible”
> and is officially suggested e.g. by Maven guidelines for writing
> pom.xml files (and also Apache Ant suggests to always use
> source/target). It is also used in the build files, to allow people
> (e.g. from Linux distributions) to use newer JDKs to produce class
> files that work with older JDKs. This type of cross compiling works
> fine if you check the above compatibility while being in the release
> process of the source code. This is the real reason why projects like
> Lucene use source and target: To be able to produce old class files,
> ignoring possible API incompatibilities checked otherwise.
>
People working on the JDK have also long recommended explicit use of the
-source and -target flags:
"Build Advice: Set Source, Target, and Encoding,"
https://blogs.oracle.com/darcy/entry/build_advice_set_source_target
> In addition, lots of projects use an additional approach to check for
> compatibility with older JDK versions because the older rt.jar for the
> bootclasspath is not easily accessible: There is a plugin called
> “animal-sniffer” (http://mojo.codehaus.org/animal-sniffer/) that has
> pre-compiled signature lists of older JDK versions (public available
> on Maven Central). You can then check the byte code of your class
> output and validate that no JDK methods are used that are not in the
> signatures files. In that case, it’s also enough to compile using
> source/target 1.6 with any newer JDK, and then check all method
> signatures in the byte code. This is much easier to set up for
> developers than downloading complete JDKs just to get older rt.jar
> files. Again, if older rt.jar files would be accessible as artifacts
> on Maven Central, this would be obsolete, too.
>
> As mentioned in response to Jon’s mail, I would suggest to use default
> method interfaces only for **new** methods. You already mentioned
> that, too. I would suggest to revert
> http://hg.openjdk.java.net/jdk8/awt/jdk/rev/e04467fa13af because the
> changes inside are only cosmetics to the class library code and bring
> no new features for the user.
>
> My heavy complaining here was targeted to direct your attention to
> side-effects of your changes to the class library/compiler. Oracle and
> Sun always kept hard backwards compatibility, so the change in this
> commit breas more builds outside than it helps. Sorry for the heated
> discussion.
>
As the author of the following document, I admit the topic is rather
dry, but we use a nuanced compatibility policy when evolving the JDK:
> 1. Don't break binary compatibility (as defined in the Java
> Language Specification).
> 2. Avoid introducing source incompatibilities.
> 3. Manage behavioral compatibility changes.
Much more discussion and examples in
"OpenJDK Developers' Guide, Version 0.777,"
http://cr.openjdk.java.net/~darcy/OpenJdkDevGuide/OpenJdkDevelopersGuide.v0.777.html
Cheers,
-Joe
> Uwe
>
> -----
>
> Uwe Schindler
>
> uschindler at apache.org
>
> Apache Lucene PMC Member / Committer
>
> Bremen, Germany
>
> http://lucene.apache.org/
>
> *From:*Joe Darcy [mailto:joe.darcy at oracle.com]
> *Sent:* Friday, March 01, 2013 2:25 AM
> *To:* Uwe Schindler
> *Cc:* 'Maurizio Cimadamore'; lambda-dev at openjdk.java.net;
> compiler-dev at openjdk.java.net; Robert Muir
> *Subject:* Re: Regression in JDK8 build 78: javac complains about
> missing Class#isAnnotationPresent
>
> On 2/28/2013 2:36 PM, Uwe Schindler wrote:
>
> Thanks Maurizio,
>
> that’s true, somebody added the –Xlint:-options tot he ANT build file.
>
> This is still no answer to the source of the problem
>
>
> As I'm composing this message, it is less than four hours after your
> initial email was first sent to OpenJDK lists. In that time, your
> email has gotten responses from multiple people working on the JDK. As
> we are over six months before the planned ship date for JDK 8,
> addressing this particular issue does not necessarily need preempt
> other ongoing work so that it can be fully resolved today.
>
>
> making again a new Oracle Java version unusable to compile millions of
> open source projects (Lucene is just an example) – this status quo
> seems to repeat on every new major version. Last time it was the
> serious Hotspot bug corrumpting loops in Java7 GA.
>
>
> Well, it sounds like Lucene is testing with JDK 8 more than a few
> weeks ahead of its ship date, so there should be plenty of time to fix
> correctness bugs that are found and reported ;-)
>
> It is very helpful for external projects to run tests of their code on
> JDK 8 builds along the way to supplement the testing done by the JDK team.
>
> As for the technical details of what is going on, the
> isAnnotationPresent method in the java.lang.reflect.AnnotatedElement
> interface has been turned into a default method:
>
> http://bugs.sun.com/view_bug.do?bug_id=8007113
>
> This change was introduced in b77 and allows some sharing of code
> among the various classes implementing AnnotatedElement, including
> java.lang.Class, java.lang.reflect.{Method, Constructor}.
>
> For reasons I'll describe shortly, when compiling under a -source
> setting earlier than source 8, code that references
> isAnnotationPresent in the implementing classes (or the declaring
> interface) will not see the method as being present. Code that does
> not reference this method will continue to compile under "-source OLD
> -target OLD" (with the usual caveats) and code that references this
> method will see the method as expected under -source 8.
>
> Now, for the central technical question: (using concrete values) how
> should new-in-Java-8 language constructs in the bootclasspath appear
> to code being compiled under -source 6? This question is outside of
> the Java Language Specification, which assumes only a single source
> version exists at any one time, and has no clear-cut answer. As of
> today, as a matter of policy javac makes default methods invisible to
> code being compiled under source versions earlier than 8. Since most
> default methods added in JDK 8 will be for new methods on interfaces,
> this will usually do what people want when compiling for older
> releases (but setting the bootclasspath is the way to be sure you're
> getting the version of the libraries you should have).
>
> Since AnnoatedElement.isAnnotationPresent is an existing method that
> is now a default method, is it rendered invisible to code being
> compiled under older source versions (when the recommendation of
> setting bootclasspath has not been followed).
>
> Now javac could be made to special-case isAnnotationPresent or change
> its policy and make all default methods visible under older source
> levels, but we are more likely to partially revert the library change
> to the public implementations of AnnotatedElement by giving them
> implementations that called the method defined in the interface.
>
> Cheers,
>
> -Joe
>
>
> Every public Java project has somewhere in their build file “-target
> 1.6 -source 1.6” (or another older version), because otherwise you
> cannot run the generated class files with older Java versions.
> Compiling with a custom bootclasspath is a good idea to **validate**
> that your code actually is compliant. But if you need to use the
> bootclasspath, you need to have the older JDK version installed - in
> that case you could compile with it, too.
>
> The intention here is to just “test” the class files with newer JDK
> versions which is now impossible, without hacking the whole build in
> an incompatible way. If this is not fixed, we will suggest to users,
> not to upgrade to JDK8 once it is out – because we cannot test the
> class files with JDK 8 (and we have already seen lots of hotspot
> issues making Apache Lucene crash/fail). The same procedure as every
> year – ahm Java version.
>
> Of course to produce Java 6 class file format, one could use only
> “-target 1.6” and don’t pass “-source 1.6” (so let it default to 1.8),
> but this does not help if you build your project with Apache Ant
> (maybe doesn’t help with Maven, too):
>
> [javac] Compiling 113 source files to C:\Users\Uwe
> Schindler\Projects\lucene\trunk-lusolr3\lucene\build\test-framework\classes\java
>
> [javac]
>
> [javac] WARNING
>
> [javac]
>
> [javac] The -source switch defaults to 1.8 in JDK 1.8.
>
> [javac] If you specify -target 1.6 you now must also specify
> -source 1.6.
>
> [javac] Ant will implicitly add -source 1.6 for you. Please
> change your build file.
>
> So you no longer have the chance to produce javac 1.6 compliant class
> files without bootclasspath (using common build tools like Apache
> ANT). This makes JDK8 unusable.
>
> Sorry for complaining,
>
> But that’s a major regression!
>
> Uwe
>
> -----
>
> Uwe Schindler
>
> uschindler at apache.org <mailto:uschindler at apache.org>
>
> Apache Lucene PMC Member / Committer
>
> Bremen, Germany
>
> http://lucene.apache.org/
>
> *From:*Maurizio Cimadamore [mailto:maurizio.cimadamore at oracle.com]
> *Sent:* Thursday, February 28, 2013 11:15 PM
> *To:* Uwe Schindler
> *Cc:* 'Joe Darcy'; lambda-dev at openjdk.java.net
> <mailto:lambda-dev at openjdk.java.net>; compiler-dev at openjdk.java.net
> <mailto:compiler-dev at openjdk.java.net>
> *Subject:* Re: Regression in JDK8 build 78: javac complains about
> missing Class#isAnnotationPresent
>
> On 28/02/13 21:31, Uwe Schindler wrote:
>
> I know about this warning and it generally appears on Java 7, but it was****not** printed out in that case (8b78)! The log I posted was the complete printout from javac.
>
> This warning is a Xlint warning - so it's possible that you are
> compiling the project with a custom set of Xlint warnings that doesn't
> include this category (called 'options').
>
> Maurizio
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/compiler-dev/attachments/20130301/ec5048fa/attachment.html
More information about the compiler-dev
mailing list