My Java Multiline String project stopped building when compiling with Java 10 because tools.jar
has been removed since Java 9.
When the tools.jar
dependency is specified like this:
pom.xml
... <dependencies> <dependency> <groupId>sun.jdk</groupId> <artifactId>tools</artifactId> <version>LATEST</version> <scope>system</scope> <systemPath>${java.home}/../lib/tools.jar</systemPath> </dependency> </dependencies> ...
The build failed with output:
------------------------------------------------------------------------ BUILD FAILURE ------------------------------------------------------------------------ Total time: 0.347 s Finished at: 2018-08-29T21:10:41+01:00 Final Memory: 6M/24M ------------------------------------------------------------------------ Failed to execute goal on project multiline-string: Could not resolve dependencies for project org.adrianwalker:multiline-string:jar:0.2.1: Could not find artifact sun.jdk:tools:jar:LATEST at specified path /usr/local/jdk-10.0.1/../lib/tools.jar -> [Help 1]
Simply removing the dependency fixes the build and the project compiles without error. So where are the classes which were in the tools.jar
com.sun.tools.javac
packages?
In JDK versions 1.8 and lower:
cd /usr/local/jdk1.8.0_172 unzip -l ./lib/tools.jar | grep com/sun/tools/javac/tree/TreeMaker.class 47366 2018-03-28 21:40 com/sun/tools/javac/tree/TreeMaker.class
In JDK version 10:
cd /usr/local/jdk-10.0.1 unzip -l ./jmods/jdk.compiler.jmod | grep com/sun/tools/javac/tree/TreeMaker.class warning [./jmods/jdk.compiler.jmod]: 4 extra bytes at beginning or within zipfile (attempting to process anyway) 64266 2018-03-26 18:16 classes/com/sun/tools/javac/tree/TreeMaker.class
I still want to be able to compile this library will all JDK versions from 1.6 onwards without creating another project for versions 9 and 10. To do this we can move the tools.jar
dependency to a profile which is only activated for older JDKs:
pom.xml
... <profiles> <profile> <activation> <jdk>[1.6,9)</jdk> </activation> <dependencies> <dependency> <groupId>sun.jdk</groupId> <artifactId>tools</artifactId> <version>LATEST</version> <scope>system</scope> <systemPath>${java.home}/../lib/tools.jar</systemPath> </dependency> </dependencies> </profile> </profiles> ...
The line <jdk>[1.6,9)</jdk>
specifies a version range using the Apache Maven Enforcer range syntax. In this case, include all versions from 1.6 upto but not including 9.
Aside from pom.xml changes, the Java code and usage remains identical to the original project.
Java 9/10 module system
This all only works because the maven-compiler-plugin
is configured with source
and target
set to 1.6
:
pom.xml
... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> ...
If we want to use Java 9/10 lanuage features, setting source
and target
to 10
will give these errors:
Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project multiline-string: Compilation failure: Compilation failure: org/adrianwalker/multilinestring/MultilineProcessor.java:[3,27] package com.sun.tools.javac.model is not visible (package com.sun.tools.javac.model is declared in module jdk.compiler, which does not export it to the unnamed module) org/adrianwalker/multilinestring/MultilineProcessor.java:[4,27] package com.sun.tools.javac.processing is not visible (package com.sun.tools.javac.processing is declared in module jdk.compiler, which does not export it) org/adrianwalker/multilinestring/MultilineProcessor.java:[5,27] package com.sun.tools.javac.tree is not visible (package com.sun.tools.javac.tree is declared in module jdk.compiler, which does not export it to the unnamed module) org/adrianwalker/multilinestring/MultilineProcessor.java:[6,27] package com.sun.tools.javac.tree is not visible (package com.sun.tools.javac.tree is declared in module jdk.compiler, which does not export it to the unnamed module)
In this case we must correctly use the new Java Module System. To resolve the above errors first we need a module-info.java
in the project root specifying a module name and the module's requirements:
module-info.java
module org.adrianwalker.multilinestring { requires jdk.compiler; }
Next we need to export the required packages in the jdk.compiler
module and make them visible to our org.adrianwalker.multilinestring
module:
pom.xml
... <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <source>10</source> <target>10</target> <compilerArgs> <arg>--add-exports</arg> <arg>jdk.compiler/com.sun.tools.javac.model=org.adrianwalker.multilinestring</arg> <arg>--add-exports</arg> <arg>jdk.compiler/com.sun.tools.javac.processing=org.adrianwalker.multilinestring</arg> <arg>--add-exports</arg> <arg>jdk.compiler/com.sun.tools.javac.tree=org.adrianwalker.multilinestring</arg> </compilerArgs> </configuration> </plugin> ...
And now the project should build without errors and work just as before.
Source Code
- Github - multiline-string
- Github - multiline-string (Java 10 branch)