【问题标题】:Can I provide runtime compiler access when running with JRE in Java 9+?在 Java 9+ 中使用 JRE 运行时,我可以提供运行时编译器访问权限吗?
【发布时间】: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.JavacTooljdk.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 jlinkjmod 怎么样?另外,为您的用例考虑过using the ToolProvider
  • @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


【解决方案1】:

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

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

用户下载 JDK 应该不会感到惊讶,因为他们正在使用 JDK 功能:编译代码。

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

【讨论】:

  • 当我说“他们自己的代码”时......开发人员不是我们的目标客户,所以他们使用的大多数自定义代码 sn-ps 都是由第三方编写的(他们自己的 IT 支持,我们的产品论坛等)事实上,我们捆绑了 JRE,因此用 JDK 替换它会使我们的应用程序膨胀,但这绝对是我们考虑的最坏情况解决方案。
  • 使用 Java 11,这个解决方案变得非常简单,因为不再有 JRE。那些知道如何创建更小的运行时环境的人应该知道如何包含编译器。
猜你喜欢
  • 2015-06-17
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-08
  • 2016-11-19
  • 1970-01-01
相关资源
最近更新 更多