【发布时间】:2018-05-31 15:51:58
【问题描述】:
我正在将应用程序迁移到 Java 10。我们的应用程序通常使用 JRE 运行,但我们允许用户通过捆绑 tools.jar 并使用反射按需加载 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());
}
}
这是必要的,因为javax.tools.ToolProvider.getSystemJavaCompiler() 在从 JRE 运行时返回 null。我们的方法在 Java 8 上运行良好,但在 Java 9 中删除了 tools.jar,而我需要的类 com.sun.tools.javac.api.JavacTool 在 jdk.compiler 模块中,它仍然是 JDK 的一部分,但不是 JRE。
在启动 JRE 时有没有办法加载 jdk.compiler 模块?我怀疑不是,基于this answer,我尝试使用--add-module 导致:
java.lang.module.FindException: JMOD format not supported at execution time
我还缺少其他解决方案吗?
【问题讨论】:
-
尝试创建custom runtime image using
jlink和jmod怎么样?另外,为您的用例考虑过using theToolProvider? -
@manouti 根据我的建议,我的意思是创建一个自定义运行时映像,至于其中的实现,使用
ToolProvider而不是tools.jar -
这真是个奇怪的问题。如果应用程序在 JRE 8 上运行,那么用户也需要在系统上安装 JDK 8。也许问题中的代码不是关于 JRE 而是 tools.jar 默认不在类路径上?如果是这样,则在 JDK 9 和更新版本中不需要此代码,因为 java.compiler 和 jdk.compiler 模块默认已解析。
-
这个问题还是很奇怪的。如果您使用的是 JRE 8,那么它在哪里找到 tools.jar?系统上必须有 JDK,您如何检查它是否与您正在运行的 JRE 版本相同。如果你真的想在 JRE 上运行,那么我认为你必须创建一个新的 VM 来运行编译器。
-
JDK 9 和更新版本的等效方法是运行
jlink以创建包含 jdk.compiler 模块的运行时映像。
标签: java java-9 java-platform-module-system java-10 jmod