I'm migrating an application to Java 10. Our application normally runs with the JRE, but we allow users to compile bits of their own custom code by bundling tools.jar
and using reflection to load a JavacTool
instance on demand. Our method looks like:
public static JavaCompiler getJavaCompiler() {
String toolJarName = "tools.jar";
File file = getResourceForClass("tools.jar");
try {
file = file.getCanonicalFile();
} catch (IOException ignore) {
}
if (!file.exists())
throw new RuntimeException("Can't find java tools file: '"+file+"'");
try {
URL[] urls = new URL[]{ file.toURI().toURL() };
URLClassLoader cl = URLClassLoader.newInstance(urls);
return Class.forName("com.sun.tools.javac.api.JavacTool", false, cl).asSubclass(JavaCompiler.class).newInstance();
} catch (Exception e) {
throw new RuntimeException("Can't find java compiler from '"+file+"': "+e.getMessage());
}
}
This is necessary because javax.tools.ToolProvider.getSystemJavaCompiler()
returns null when running from the JRE. Our method worked well with Java 8, but tools.jar
was removed in Java 9, and the class I need com.sun.tools.javac.api.JavacTool
is in the jdk.compiler
module which remains part of the JDK, but not the JRE.
Is there any way to load the jdk.compiler
module when launching the JRE? I suspect it's not, based on this answer, and my attempts to use --add-module
result in:
java.lang.module.FindException: JMOD format not supported at execution time
Is there another solution I'm missing?
jlink
andjmod
? Also, thought of using theToolProvider
for your use case? – Predestinationjava.util.spi.ToolProvider
in your GitHub sample work even if no JDK is present? I doubt that, which means that this probably won't help the OP. – CimbriToolProvider
instead oftools.jar
– Predestinationjdk.compiler
isn't available with the Oracle JRE. When runningjava --list-modules
with Java 10 JRE you'll noticejdk.compiler
is conspicuously absent. – Arianaarianejava.util.spi.ToolProvider
rather than, say,javax.tools.ToolProvider.getSystemJavaCompiler()
, but a custom runtime image seems like it's the solution (and also way more straightforward than I expected). If you add this as an answer I'll accept it. – Arianaarianetools.jar
as a resource. We actually bundle the JRE with our application, so we could ensure it's the same version, but interestingly enough we've been bundlingtools.jar
from 8u25 and JRE 8u162, unnoticed by all. It worked fine until we migrated to Java 10. – Arianaarianejlink
to create a run-time image that includes the jdk.compiler module. – Rolph