当前教程
使用 --add-modules--add-reads 扩展模块图
这是系列的最后一篇!

使用 --add-modules--add-reads 扩展模块图

从一组初始的根模块开始,模块系统计算所有它们的依赖项并构建一个图,其中模块是节点,它们的读写关系是定向边。可以使用命令行标志 --add-modules--add-reads 扩展此模块图,它们分别添加模块(及其依赖项)和读写边。前者有一些用例,后者非常小众,但无论如何,了解它们总是有好处的。

注意:您需要了解 模块系统基础知识如何从命令行构建和启动 才能充分利用本文。

使用 --add-modules 添加根模块

选项 --add-modules $MODULESjavacjlinkjava 上可用,并接受以逗号分隔的模块列表,它将这些模块添加到根模块集中。(根模块构成模块解析开始的初始模块集。)这使您可以将模块(及其依赖项)添加到模块图中,否则这些模块不会出现,因为初始模块不依赖于它们(直接或间接)。

--add-modules 选项有三个特殊值

  • ALL-DEFAULT 是在 从类路径启动代码 时作为根模块选择的模块集。当应用程序是托管其他应用程序的容器时,这很有用,而这些应用程序又可能依赖于容器本身不需要的模块。
  • ALL-SYSTEM 将所有 系统模块 添加到根集,测试工具有时需要这样做。此选项将导致解析许多模块;通常,应优先使用 ALL-DEFAULT
  • ALL-MODULE-PATH 将模块路径上找到的所有模块添加到根集。Maven 等构建工具提供此功能,这些工具已经确保模块路径上的所有模块都是必需的。它也是将自动模块添加到根集的便捷方法。

前两个仅在运行时有效,用于本文未讨论的非常具体的用例。最后一个非常有用:使用它,模块路径上的所有模块都成为根模块,因此它们全部进入模块图。

--add-modules 后的空格可以用等号 = 替换,这有助于某些工具配置:--add-modules=...

添加模块的用例

--add-modules 的一个用例是添加 可选依赖项,这些依赖项在其他情况下不需要,因此不会进入模块图。例如,假设一个项目对 java.sql 有可选依赖项,但该模块在其他情况下不需要

# launch without java.sql
$ java
    --module-path example.jar:deps
    --module com.example/com.example.Main

# launch with java.sql
$ java
    --module-path example.jar:deps
    --add-modules java.sql
    --module com.example/com.example.Main

另一个用例是在 使用 jlink 创建运行时映像 时定义根模块集。

添加模块时,可能需要让其他模块读取它们,所以接下来让我们这样做。

使用 --add-reads 添加读写边

编译器和运行时选项 --add-reads $MODULE=$TARGETS$MODULE 添加到以逗号分隔的列表 $TARGETS 中所有模块的读写边。这允许 $MODULE 访问这些模块导出的包中的所有公共类型,即使 $MODULE 没有提到它们的 requires 子句。如果 $TARGETS 设置为 ALL-UNNAMED$MODULE 甚至可以读取未命名模块。

--add-reads 后的空格可以用等号 = 替换,这有助于某些工具配置:--add-reads=.../...

添加读写的示例

让我们回到之前的示例,其中代码使用了 java.sql,但不想总是依赖它。可选依赖项的另一种方法是不列出依赖项,而是使用 --add-modules--add-reads 添加它(这很少有用,通常不推荐 - 只是一个示例)

# this only shows launch, but compilation
# would also need the two options
$ java
    --module-path example.jar:deps
    --add-modules java.sql
    --add-reads com.example=java.sql
    --module com.example/com.example.Main

上次更新: 2021 年 9 月 14 日


当前教程
使用 --add-modules--add-reads 扩展模块图
这是系列的最后一篇!