Uwe Schindler created LUCENE-4808:
-------------------------------------

             Summary: Add workaround for a JDK 8 "class library bug" which is 
still under discussion any may *not* be fixed
                 Key: LUCENE-4808
                 URL: https://issues.apache.org/jira/browse/LUCENE-4808
             Project: Lucene - Core
          Issue Type: Bug
          Components: general/build
    Affects Versions: 4.1, 5.0
            Reporter: Uwe Schindler
            Assignee: Uwe Schindler


With JDK8 build 78 there was introduced a backwards compatibility regression 
which may not be fixed until release, because Oracle is possibly accepting this 
backwards break regarding cross-compilation to JDK6.

The full thread on the OpenJDK mailing list: 
[http://mail.openjdk.java.net/pipermail/compiler-dev/2013-February/005737.html] 
(continues in next month: 
http://mail.openjdk.java.net/pipermail/compiler-dev/2013-March/005748.html)

*In short:* JDK 8 adds so called default implementations on interfaces (means 
you can add a new method to an interface and provide a "default" 
implementation, so code implementing this interface is not required to 
implement the new method. This is really cool and would also help Lucene to 
make use of Interfaces instead of abstract classes which don't allow 
polymorphism).

In Lucene we are still compatible with Java 7 and Java 6. So like millions of 
other open source projects, we use "-source 1.6 -target 1.6" to produce class 
files which are Java 1.6 conform, although you use a newer JDK to compile. Of 
course this approach has problem (e.g. if you use older new methods, not 
available in earliert JDKs). Because of this we must at least compile Lucene 
with a JDK 1.6 legacy JDK and also release the class files with this version. 
For 3.6, the RM has to also install JDK 1.5 (which makes it impossible to do 
this on Mac). So -source/-target is a alternative to at least produce 1.6/1.5 
compliant classes. According to Oracle, this is *not* the correct way to do 
this: Oracle says, you have to use: -source, -target and -Xbootclasspath to 
really crosscompile -> and the last thing is what breaks here. To correctly set 
the bootclasspath, you need to have an older JDK installed or you should be 
able to at least download it from maven (which is not available to my 
knowledge).

The problem with JDK8 is now: If you compile with -source/-target but not the 
bootclasspath, it happens that the compiler does no longer understand new JDK8 
class file structures in the new rt.jar, so producing compile failures. In the 
case of this bug: AnnotatedElement#isAnnotationPresent() exists since Java 1.5 
in the interface, but all implementing classes have almost the same 
implementation: "return getAnnotation(..) != null;". So the designers of the 
class library decided to move that method as so called default method into the 
interface itsself, removing code duplication. If you then compile code with 
"-source 1.6 -target 1.6" using that method, the javac compier does not know 
about the new default method feature and simply says: "Method not found in 
java.lang.Class":

{noformat}
    [javac] Compiling 113 source files to C:\Users\Uwe 
Schindler\Projects\lucene\trunk-lusolr3\lucene\build\test-framework\classes\java
    [javac] C:\Users\Uwe 
Schindler\Projects\lucene\trunk-lusolr3\lucene\test-framework\src\java\org\apache\lucene\util\TestRuleSetupAndRestoreClassEnv.java:134:
 error: cannot find symbol
    [javac]     if (targetClass.isAnnotationPresent(SuppressCodecs.class)) {
    [javac]                    ^
    [javac]   symbol:   method isAnnotationPresent(Class<SuppressCodecs>)
    [javac]   location: variable targetClass of type Class<?>
    [javac] Note: Some input files use or override a deprecated API.
    [javac] Note: Recompile with -Xlint:deprecation for details.
    [javac] 1 error
{noformat}

But until the Oracle people have a good workaround (I suggested to still 
implement the method on the implementation classes like Class/Method/... but 
delegate to the interface's default impl), we can quickly commit a replacement 
of this broken method call by (getAnnotation(..) != null). I want to do this, 
so we can enable jenkins builds with recent JDK 8 again.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to