使用 --add-modules
和 --add-reads
扩展模块图
从一组初始的根模块开始,模块系统计算所有它们的依赖项并构建一个图,其中模块是节点,它们的读写关系是定向边。可以使用命令行标志 --add-modules
和 --add-reads
扩展此模块图,它们分别添加模块(及其依赖项)和读写边。前者有一些用例,后者非常小众,但无论如何,了解它们总是有好处的。
注意:您需要了解 模块系统基础知识 和 如何从命令行构建和启动 才能充分利用本文。
使用 --add-modules
添加根模块
选项 --add-modules $MODULES
在 javac
、jlink
和 java
上可用,并接受以逗号分隔的模块列表,它将这些模块添加到根模块集中。(根模块构成模块解析开始的初始模块集。)这使您可以将模块(及其依赖项)添加到模块图中,否则这些模块不会出现,因为初始模块不依赖于它们(直接或间接)。
--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 日