在Java 9+中使用JRE运行时,我可以提供运行时编译器访问吗?

我正在将应用程序迁移到Java 10.我们的应用程序通常使用JRE运行,但我们允许用户通过捆绑tools.jar并使用reflection按需加载JavacTool实例来编译自己的自定义代码。 我们的方法如下:

 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()); } } 

这是必要的,因为从JRE运行时, javax.tools.ToolProvider.getSystemJavaCompiler()返回null。 我们的方法适用于Java 8,但在Java 9中删除了tools.jar ,而我需要com.sun.tools.javac.api.JavacTool的类在jdk.compiler模块中,它仍然是JDK的一部分,但不是JRE。

有没有办法在启动JRE时加载jdk.compiler模块? 我怀疑它不是,根据这个答案 ,我尝试使用--add-module导致: java.lang.module.FindException: JMOD format not supported at execution time

我还缺少另一种解决方案吗?

IMO对您的问题最简单的解决方案是保持简单,并要求用户下载JDK而不是JRE:

…但我们允许用户编译他们自己的自定义代码

用户下载JDK应该不足为奇,因为他们正在使用JDKfunction:编译代码。

如果那是不可能的,那么您可能想尝试@nullpointer在评论中建议的jlink解决方案。