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?
IMO the simplest solution to your problem is to keep it simple and require users to download the JDK instead of the JRE:
... but we allow users to compile bits of their own custom code
It should come to no surprise to the users to download a JDK since, well, they are using a JDK feature: compiling code.
If that's not possible, then you may want to try the jlink
solution that @nullpointer suggests in the comments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With