是否可以在javac(JDK 9)中混合使用--class-path和--module-path?依赖模块路径 ~> 类路径依赖类路径 ~ > 模块路径

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

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

我可以理解使用 和 在同一时间(编译)是非法的,但javac不会以任何方式警告我。--class-path--module-path


答案 1

可以并行使用类路径和模块路径,但需要考虑一些详细信息。

依赖模块路径 ~> 类路径

显式模块(在模块路径上带有模块描述符的 JAR)无法读取未命名模块(类路径上的 JAR) - 这是故意这样做的,以防止模块化 JAR 依赖于“类路径的混乱”。

由于模块必须需要其所有依赖项,并且这些依赖项只能由其他命名模块(即类路径上的 JAR)实现,因此模块化JAR的所有依赖项必须放在模块路径上。是的,即使是非模块化的JAR,它们也会变成自动模块

有趣的是,自动模块可以读取未命名的模块,因此它们的依赖项可以位于类路径上。

依赖类路径 ~ > 模块路径

如果编译非模块化代码或从非模块化 JAR 启动应用程序,则模块系统仍在运行,并且由于非模块化代码不表示任何依赖项,因此它不会从模块路径解析模块。

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


答案 2

我相信同时使用和选项并不违法。可以同时使用两者,因为即使您没有显式指定类路径,它也默认为当前目录。--classpath--module-path

来自消息和 javac 工具文档的详细信息javac -help -

--module-path <path>, -p <path>

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

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

指定查找用户类文件和注释处理器的位置

如果未指定 --class-path-classpath-cp,则用户类路径为当前目录


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

但是,如果不使它们成为自动模块,而只是指定 --class-path some.jar 紧挨着 --module-path ,那么 javac 似乎会忽略 claspath 并抛出“包 yyy 未找到”和其他“未找到”错误。

如果您不使它们自动,它将被视为模块系统的未命名模块,并且 -

实际上,命名模块甚至不能声明对未命名模块的依赖关系。此限制是有意为之,因为允许命名模块依赖于类路径的任意内容将使可靠的配置变得不可能。

此外,未命名的模块将导出其所有包,因此自动模块中的代码将能够访问从类路径加载的任何公共类型。

但是,使用类路径中的类型的自动模块不得将这些类型公开给依赖于它的显式模块,因为显式模块不能声明对未命名模块的依赖关系。

例如,如果显式模块中的代码引用了 中的公共类型,并且该类型的签名引用了仍在类路径上的某个 JAR 文件中的类型,则 中的代码将无法访问该类型,因为不能依赖于未命名的模块。com.foo.appcom.foo.barcom.foo.appcom.foo.app

这可以通过暂时视为自动模块来补救,以便其代码可以从类路径访问类型,直到类路径上的相关 JAR 文件可以被视为自动模块或转换为显式模块。com.foo.app


推荐