In the first post, I described what needed to be done to make Che
workspaces run Java 9 (which means getting the Che server to run
Java 9 too).
Now I want to explain what had to be done so contributors to the
Che project could compile and run with Java 9.
The latest Eclipse Che stable release (v5) was designed and built
on top of Java 8. So when a new version of the JDK, Java 9, was
released we had to ensure that Eclipse Che could be built and run
on top of Java 9 as well.
Eclipse Che uses many dependencies and in order to be compliant
with Java 9 all dependencies need to be compliant as well. So
making Eclipse Che compliant with Java 9 required a lot of
updates.
Compiling Eclipse Che with Java 9
Maven and Java 9
We had numerous failures when we first tried to build Eclipse Che
with Java 9. Eclipse Che uses maven to build the project but when
trying to build it most of the existing maven plugins were not
ready to use Java 9 so we had to wait for those plugins to be
updated.
Plus, as an Eclipse project when we update a component we have to
file a CQ (Contribution Questionnaire) for each one. With 20+ plugins to update it meant getting
approval for each one.
Update plugins · eclipse/che-parent@d18be1d
_Change-Id: I90667d9a0a4d64294c10ac647b1cb176c3811fa1
Signed-off-by: Florent BENOIT_github.com
After those plugins were updated, we still had issues around some
Java components. Most of the failures were linked to the fact that
in Java 9 the system class loader is no longer a
URLClassLoader
and many components assumed that and performed a cast to
URLClassLoader
…which would fail.
JDK Reflection / Internal Classes
The easiest problem to solve was with JDK reflection. We had some
methods that performed internal introspection of JDK classes but
these methods were not used anymore so instead of trying to fix
them we simply removed them!
ai Remove unused SystemInfo attributes (cpu, freeMemory,
totalMemory) by benoitf · Pull Request #6946…
_What does this PR do? In Java9, relying on “internal fields” of
classes is not permitted by default. Only public…_github.com
JDK and
**tools.jar**
Until Java 9, when you required classes provided by
tools.jar
you had to add a system dependency in your pom.xml by using the
path to the
tools.jar
file:
sun.jdt
tools
system
${java.home}/../lib/tools.jar</systemPath
</dependency> With Java 9, `tools.jar` is no longer there
(modularity!) and classes are available with the JVM so we
instead added this dependency in a maven profile that is only
enabled if the Java version is lower than Java 9.
java8-tools
(,1.9)
sun.jdt
tools
system
${java.home}/../lib/tools.jar
**Compiling?** At that point when we tried to compile Eclipse
Che by disabling all unit tests and checks it _almost_ worked.
All the modules were marked `_“build success”_` until the last
module that tried to build GWT app which…failed…oh no! **GWT and
Java9** This meant we had to upgrade to GWT 2.8.2 to get Java 9
compliance. Note that you still have to use Java 8 language
features, but GWT 2.8.2 allows you to use a Java 9 runtime.
[**GWT Project** _The 2.4 General Availability release of GWT
contains new App Engine tools for Android, incremental RPC
tooling,
Apps…_www.gwtproject.org](http://www.gwtproject.org/release-notes.html#Release_Notes_2_8_2
"http://www.gwtproject.org/release-notes.html#Release_Notes_2_8_2")[](http://www.gwtproject.org/release-notes.html#Release_Notes_2_8_2)
After all these compiling dependencies updates it was finally
possible to build Eclipse Che with Java9! But we really wanted
to have unit tests working as well! ;-) **Che and Unit Tests
with Java9** We were using Mockito 1.x in Eclipse Che but to get
Java 9 support we needed Mockito 2.10. This meant converting all
existing tests to Mockito 2.x. This was quite a bit of work
because some of classes which were deprecated in 1.x were
removed in 2.x while other methods (like `any()`) handle `null`
differently. Last but not least, we were using a maven artifact
named `mockito-all` and this artifact is no longer supported on
2.x so we had to remove it everywhere it was used (many, many
places…). Now tests could be launched but some failures were
still reported on EclipseLink and Apache Lucene — the versions
that we were using of those were not compliant with Java 9.
After upgrading EclipseLink to 2.7.0, and Lucene to 7.0.1 the
issues were solved. For Lucene we’d previously used version
5.2.1 so it was a big update to move to 7.0.1. **GWT Mockito
**As before the last unit tests that needed fixing were related
to the GWT Mockito tests. Specifically, there was an issue with
`classloaders` ``` Caused by: java.lang.IllegalAccessError:
class jdk.internal.reflect.ConstructorAccessorImpl loaded by
com/google/gwtmockito/GwtMockitoTestRunner$GwtMockitoClassLoader
cannot access jdk/internal/reflect superclass
jdk.internal.reflect.MagicAccessorImpl at
java.base/java.lang.ClassLoader.defineClass1(Native Method) at
java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1007)
at
java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:868)
at javassist.Loader.findClass(Loader.java:377) at
com.google.gwtmockito.GwtMockitoTestRunner$GwtMockitoClassLoader.findClass(GwtMockitoTestRunner.java:421)
``` A pull request was merged but we have not yet released.
[**Make jdk.internal.reflect package being loaded by the
standard classloader by benoitf · Pull…** _It avoids error like
Caused by: java.lang.IllegalAccessError: class
jdk.internal.reflect.ConstructorAccessorImpl
loaded…_github.com](https://github.com/google/gwtmockito/pull/73
"https://github.com/google/gwtmockito/pull/73")[](https://github.com/google/gwtmockito/pull/73)
With all the updates and patches we finally had Eclipse Che
compiling with all unit tests when using Java 9 (my tests were
with Oracle JDK on macOS) ``` java version "9.0.1"Java(TM) SE
Runtime Environment (build 9.0.1+11)Java HotSpot(TM) 64-Bit
Server VM (build 9.0.1+11, mixed mode) ``` ### Running OK
great — Eclipse Che was compiling, tests were working, but could
we launch Che with Java 9? Quick answer…no :-( Eclipse Che uses
APIs provided in the `javax` namespace (`javax.activation` and
`javax.xml.bind`). With Java 9, all packages that are not in
the`java` namespace are not exposed by default. So we had to
enable extra modules when using Java 9 or higher:
JAVA\_OPTS="$JAVA\_OPTS --add-modules java.activation
--add-modules java.xml.bind" You may notice that the name of the
modules are just `java.xxx` not `javax.xxx` — that’s not a typo,
`java.activation` provides the `javax.activation` package at
runtime. With that flag Eclipse Che was finally able to start!
But there was a big stack trace in Tomcat saying that the
`logging.properties` file was not found. This file was found in
`java.home/lib` folder previously but in Java 9 it’s moved to
the `conf` folder. So we needed a Tomcat version change that
included that fix. [**Tomcat - Dev - svn commit: r1809831 - in
/tomcat/tc8.5.x/trunk: ./ java/org/apache/juli…** _svn commit:
r1809831 - in /tomcat/tc8.5.x/trunk: ./
java/org/apache/juli/ClassLoaderLogManager.java
webapps/docs…_tomcat.10.x6.nabble.com](http://tomcat.10.x6.nabble.com/svn-commit-r1809831-in-tomcat-tc8-5-x-trunk-java-org-apache-juli-ClassLoaderLogManager-java-webapps-l-td5067695.html
"http://tomcat.10.x6.nabble.com/svn-commit-r1809831-in-tomcat-tc8-5-x-trunk-java-org-apache-juli-ClassLoaderLogManager-java-webapps-l-td5067695.html")[](http://tomcat.10.x6.nabble.com/svn-commit-r1809831-in-tomcat-tc8-5-x-trunk-java-org-apache-juli-ClassLoaderLogManager-java-webapps-l-td5067695.html)
By using Tomcat 8.5.23 we could move forward. Finally! **Eclipse
Che is Now Compiling and Running with Java 9!** As always please
let us know your thoughts by connecting with us on twitter
@eclipse\_che or by filing issues in the Che GitHub repo at
[https://github.com/eclipse/che](https://github.com/eclipse/che)