我使用 Java 17,我正在尝试加载所有 Java SE 模块(不是 JDK)。
我尝试的代码:
AtomicInteger y = new AtomicInteger();
ModuleLayer.boot().modules().stream()
.map(Module::getName)
.sorted()
.filter(x -> x.startsWith("ja") && !x.equals("java.smartcardio"))
.forEach(x -> System.out.println("#" + y.incrementAndGet() + " | " + x));
filter
内的谓词帮助我保留onlyJava SE模块(java.se
属于我们在这里看到的:https://docs.oracle.com/en/java/javase/17/docs /api/index.html)。但即使我删除它们,模块也不会返回。
我在文件系统中看到了
java.se
模块(在 lib/src.zip/...
和 legal/java.se
内部)。它甚至存在于我的 IDE (Intellij) 的外部库中:
代码的输出:
我假设您将代码作为非模块化(类路径)应用程序的一部分运行,否则模块的
requires
指令将控制哪些模块存在。
此类应用程序的策略已随 Java 11 发生变化。在以前的版本中,
java.se
模块被用作非模块化应用程序的根模块(如果存在)。
java.lang.module
Java 10 文档:
编译时的根模块集通常是正在编译的模块集。在运行时,根模块集通常是指定给“java”启动器的应用程序模块。当在未命名模块中编译代码时,或者在运行时从类路径加载主应用程序类时,默认的根模块集是特定于实现的(在 JDK 实现中,它是模块“java.se”) ,如果可观察,以及导出 API 的每个可观察模块)。
java.lang.module
Java 11 文档:
编译时的根模块集通常是正在编译的模块集。在运行时,根模块集通常是指定给“java”启动器的应用程序模块。当在未命名模块中编译代码时,或者在运行时从类路径加载主应用程序类时,默认的根模块集是特定于实现的。在 JDK 中,默认的根模块集包含 在升级模块路径上或系统模块中可观察到的每个模块,并且在没有限定的情况下导出至少一个包。
(强调是我在引文中添加的)
这项新政策不包括java.se
本身,因为它不“导出至少一个包”。与
JDK-8205169比较:
在创建包含
java.se
且还包含不在 Java SE 中但导出 API 的 java.* 模块的运行时映像时,此[旧]策略会出现问题,例如java.json
。在编译或运行非模块化代码时,开发人员需要指定--add-modules
以确保解析运行时映像中的非 Java SE java.* 模块。第二点是,创建原始策略是为了确保默认情况下不会解析
java.corba
和 Java EE 模块(存在于 Java SE 9 和 10 中)。建议从 Java SE 11 中删除这些模块,因此该方面的政策不再相关。
更改策略,以便默认的根模块集只是升级模块路径上或导出至少一个包的系统模块中的所有可观察模块,而无需限定。