从Java 9访问com.sun.tools.javac.util

21

我正在尝试访问com.sun.tools.javac.util中的List类。这在Java 8中可以正常工作,但切换到Java 9后,我会收到以下错误:包'com.sun.tools.javac.util'声明在模块"jdk.compiler"中,该模块未将其导出到未命名模块"

我尝试将requires jdk.compiler;添加到我的module-info文件中,但这并没有解决问题。


2
在JDK9中,您需要使用javax.tools。未导出包中的类不可用。 - M. le Rutte
1
@bramhaag 这个包在Java 9中已经被弃用。你应该迁移到它们的等效实现,可以通过查看你的代码本身来描述。 - Naman
5
我刚刚查了一下那个类,没有看到任何解释为什么开发人员需要使用那个列表类而不是只使用例如ArrayList或标准工厂方法返回的专门列表之一。 - Holger
3
值得一提的是,这个类是由 Scala 的设计者 Martin Odersky 在 1.2 版本时编写的。Scala 的早期版本中 List 的外观非常相似。 - Stefan Zobel
4
在文件顶部附近的注释写道:“这不是任何受支持API的一部分。如果你编写的代码依赖于此,你要自担风险。此代码及其内部接口可能会在未经通知的情况下发生更改或删除。” http://hg.openjdk.java.net/jdk9/jdk9/langtools/file/jdk-9+181/src/jdk.compiler/share/classes/com/sun/tools/javac/util/List.java#l48 - Stuart Marks
显示剩余5条评论
2个回答

17

从长远来看,处理这种情况的安全方法是不再使用 JDK 的这些内部 API。

可以使用 jdk.compiler 模块的 API 作为 com.sun.tools.javac 包的替代。

定义了 系统 Java 编译器 及其命令行等效物 javacjavah 的实现。

特别是对于 com.sun.tools.javac.util.List,它的几乎所有未重写的自定义方法都可以基于接口 java.util.List 的实现得出。


迁移指南中的 已删除的 java.* API 列中指出 -

Java 团队致力于向后兼容性。如果应用程序在 JDK 8 中运行,只要使用受支持且用于外部使用的 API,则它将在 JDK 9 上运行。

这些包括:

  • JCP 标准、java.*javax.*
  • JDK 特定的 API,一些为 com.sun.*,一些为 jdk.*

支持的 API 可能会从 JDK 中删除,但只有在提前通知的情况下才能删除。 运行静态分析工具 jdeprscan,以查找代码是否使用了已弃用的 API。

接着,为了加强上述风险..

编译时

JDK 9 封装的内部 API 在编译时不可访问,但可以通过 --add-exports 命令行选项使其在编译时可访问。

在你的情况中:

--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED

运行时

在运行时,如果它们在JDK 8中是可访问的,那么它们将始终可访问,但在将来的版本中,它们将变得不可访问,在此时可以使用--add-exports--add-opens选项使其在运行时也可访问。


3
这些 API 并没有被废弃;它们仅仅是 javac 的内部接口,在 JDK 9 中默认情况下无法访问。除此之外,是的。 - Stuart Marks
@StuartMarks 同意。"内部API"似乎比"弃用"这个词更好?只是为了澄清,我并没有指"@Deprecated"。 - Naman
4
是的,内部的 更可取。这些东西都没有被弃用。感谢您更新。 - Stuart Marks
谢谢您的建议,@StuartMarks :) - Naman
我应该在哪里输入这个命令“--add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED”? - motionless570
显示剩余2条评论

-11

如果使用以下参数 gradle.settings,可能会有所帮助。

org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
kotlin.code.style=official

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接