是否可以在 javac (JDK 9) 中混合使用 --class-path 和 --module-path?

Is it possible to mix --class-path and --module-path in javac (JDK 9)?

当我编译一个依赖于我之前编译过的其他模块的模块时,我必须指定 --module-path <directory> 选项。这使得我依赖的模块可见。

但同时我也想让一些非模块化的Jar文件可见。但是,如果不让它们成为自动模块,而只是在 --module-path <directory> 旁边指定 --class-path some.jar,那么 javac 似乎会忽略 claspath 并抛出 "package yyy not found" 和其他 "not found" 错误。

我可以理解在同一(编译)时间使用 --class-path--module-path 是非法的,但是 javac 并没有警告我反对它无论如何。

我认为同时使用 --classpath--module-path 选项是 不违法。可以同时使用两者,即使您没有明确指定 class 路径,它 默认 到当前目录。

来自 javac -help 消息和 javac tools docs -

的详细信息
--module-path <path>, -p <path>

指定在何处查找应用程序模块

--class-path <path>, -classpath <path>, -cp <path>

指定在何处查找用户 class 文件和注释处理器

If --class-path, -classpath, or -cp aren’t specified, then the user class path is the current directory.


编辑:感谢@MouseEvent,我可能错过了问题中的部分

However if don't make them automatic modules and just specify the --class-path some.jar right next to --module-path , then javac seems to ignore the claspath and throws "package yyy not found" and other "not found" errors.

如果您不将它们设为自动,它将被视为 Module System's unnamed module 和 -

A named module cannot, in fact, even declare a dependence upon the unnamed module. This restriction is intentional, since allowing named modules to depend upon the arbitrary content of the class path would make reliable configuration impossible.

此外,unnamed 模块导出其所有包,因此 automatic 模块中的代码将能够访问任何 public 类型从 class 路径加载。

但是使用 class 路径中的类型的自动模块 不能将这些类型暴露给依赖它的显式模块 ,因为显式模块不能声明对未命名模块的依赖。

If code in the explicit module com.foo.app refers to a public type in com.foo.bar, e.g., and the signature of that type refers to a type in one of the JAR files still on the class path, then the code in com.foo.app will not be able to access that type since com.foo.app cannot depend upon the unnamed module.

这可以通过暂时将 com.foo.app 视为自动模块来解决,这样它的代码就可以从 class 路径访问类型,直到 [=64 上的相关 JAR 文件=] path 可以作为自动模块处理,也可以转换成显式模块。

您可以并行使用 class 路径和模块路径,但有一些细节需要考虑。

依赖模块路径 ~> Class 路径

显式模块(模块路径上带有模块描述符的 JAR)无法读取未命名模块(class 路径上的 JAR)- 这样做是为了防止模块化 JAR 依赖于 "the chaos of the class path".

由于模块必须需要它的所有依赖项,而这些依赖项只能由其他命名模块(即不是 class 路径上的 JAR)实现,因此模块化 JAR 的所有依赖项都必须放在模块路径上.是的,即使是非模块化的 JAR,它们也会变成 automatic modules.

有趣的是自动模块可以读取未命名的模块,所以它们的依赖可以继续class路径。

依赖关系Class路径~>模块路径

如果您编译非模块化代码或从非模块化 JAR 启动应用程序,模块系统仍在发挥作用,并且由于非模块化代码不表达任何依赖关系,它不会从模块中解析模块路径。

因此,如果非模块化代码依赖于模块路径上的工件,则需要使用 the --add-modules option 手动添加它们。不一定全部,只是那些你直接依赖的(模块系统将引入传递依赖) - 或者你可以使用 ALL-MODULE-PATH(检查链接 post,它更详细地解释了这一点) .