修补模块引发模块未找到错误

Patching module raises module not found error

我使用 jdk 11 并尝试理解 java 编译器的 --patch-module 选项。这是我的简单模块:

mdl-platform
      |
      |
      |___com.test.mdl.platform
      |            |
      |            |___ ...
      |            |
      |            |___Patch.java
      |
      |___module-info.java

module-info.java:

module com.test.mdl.plarform {
    exports com.test.mdl.platform;
}

Patch.java:

public class Patch { }

我有 Patch.java 文件,想用它来修补模块。我试过了:

I.

$ javac --patch-module com.test.mdl.platform=mdl-plarform/src/main/java/ \
                mdl-plarform/src/main/java/com/test/mdl/platform/Patch.java 
error: module not found: com.test.mdl.platform
1 error

我 运行 还有一些伪造的模块路径,它工作正常(生成了一个有效的 class 文件):

II.

$ javac --patch-module com.test.mdl.platform=some/fake/path/ \
      mdl-plarform/src/main/java/com/test/mdl/platform/Patch.java 

那么为什么第一个例子失败了,但是目录存在并且包含有效的module-info.java,但是第二个例子即使路径不存在也能正常工作?

我将留下一些关于 javac 如何与选项 --patch-module 一起工作的研究。

我。不在模块路径中的有效 --patch-module 路径和模块名称

$ javac --patch-module com.test.mdl.platform=mdl-plarform/src/main/java/ \
                mdl-plarform/src/main/java/com/test/mdl/platform/Patch.java 
error: module not found: com.test.mdl.platform
1 error

这失败了。

Javac 应用常规 module path scan 来查找在 --patch-module 等式左侧指定的模块(在此特定情况下为 com.test.mdl.platform)。

对于这个不在模块路径中的模块,它显然失败了,相关的 module not found 错误是 reported。模块 com.test.mdl.platform 不在模块路径中,因此该行为是预期的。

二.有效模块名称和假路径

$ javac --patch-module com.test.mdl.platform=some/fake/path/ \
      mdl-plarform/src/main/java/com/test/mdl/platform/Patch.java 

这有效 "ok"。

原因是 javac 检查 --patch-module 参数右侧指定的路径的正确性。 路径正确,前提是它包含(直接或间接)正在编译的文件

检查在 com/sun/tools/javac/file/Locations.java 中执行。可以看出,它只是循环遍历 Path mdl-plarform/src/main/java/com/test/mdl/platform/Patch.java 在每次迭代中获取父项并与 some/fake/path/.

进行比较

如果路径不正确,则返回 nullthe module is not being patched。在这种情况下,文件被视为属于未命名模块

三.路径存在,但既不包含 module-info.java 也不包含 module-info.class

$ javac --patch-module java.logging=mdl-plarform \ 
      mdl-plarform/src/main/java/com/test/mdl/platform/Patch.java

这工作正常。

原因是模块 java.logging 包含在运行时映像中,可以在模块查找期间找到。下一步是在目录中find either module-info.java or module-info.class。在这种情况下,它失败了,因为它不包含它,然后它回退到在成功的运行时映像中查找 module-info.class

四.有效的模块名称和模块路径,但模块名称不匹配

$ javac --patch-module java.logging=mdl-plarform/src/main/java \
      mdl-plarform/src/main/java/com/test/mdl/platform/Patch.java

mdl-plarform/src/main/java/module-info.java:1: error: module name com.test.mdl.plarform does not match expected name java.logging
module com.test.mdl.plarform {
^
error: cannot access module-info
  cannot resolve modules
2 errors

这失败了。

--patch-module 中指定的目录中找到 module-info.java 之后,然后对其进行解析并包含模块名称 is checked for equality with the name specified in the --patch-module。在这种情况下,我们有一个不匹配,所以打印了相关的错误。

我通过使用常规 java 调试器简单地调试 javac 来检查此行为。所以这样做的唯一目的是解释问题中描述的情况下发生了什么。