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

mal*_*c4k 23 java classpath java-9 module-path

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

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

我可以理解,使用--class-path--module-path在同一个(编译)时间是非法的,但javac并没有以任何方式警告我.

Nic*_*lai 30

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

依赖模块路径〜>类路径

显式模块(模块路径上具有模块描述符的JAR)无法读取未命名的模块(类路径上的JAR) - 这是为了防止模块化JAR依赖于"类路径的混乱"而完成的.

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

有趣的是,自动模块可以读取未命名的模块,因此它们的依赖关系可以在类路径上进行.

依赖类路径〜>模块路径

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

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

  • Nicolai - 你的答案是正确的,但我认为可以扩展为指出可能需要`--add-modules`选项来确保类路径代码所需的模块得到解决.最初的问题是为什么javac失败了,我认为这是因为他/她正在编译类路径上的代码,引用模块路径上的模块中的类,只需要`--add-modules`来确保模块得到解析. (8认同)

Nam*_*man 9

我认为同时使用--classpath--module-path选项并不违法.即使您没有明确指定类路径,它也可以同时使用它们,它默认为当前目录.

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

--module-path <path>, -p <path>
Run Code Online (Sandbox Code Playgroud)

指定查找应用程序模块的位置

--class-path <path>, -classpath <path>, -cp <path>
Run Code Online (Sandbox Code Playgroud)

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

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


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

但是,如果不使它们成为自动模块,只需在--module-path旁边指定--class-path some.jar,那么javac似乎忽略了claspath并抛出"package yyy not found"和其他"未找到" "错误.

如果你没有自动化,它被视为模块系统的未命名模块和 -

事实上,命名模块甚至不能声明对未命名模块的依赖.这种限制是有意的,因为允许命名模块依赖于类路径的任意内容将使得不可能进行可靠的配置.

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

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

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

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