【问题标题】:Is it possible to mix --class-path and --module-path in javac (JDK 9)?是否可以在 javac(JDK 9)中混合 --class-path 和 --module-path ?
【发布时间】:2018-02-27 12:21:15
【问题描述】:

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

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

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

【问题讨论】:

  • 两者可以混合使用,你能分享一个我们可以验证的最小例子吗?
  • 我可以理解同时(编译)时使用--class-path和--module-path是非法的,为什么会这样?
  • 混音是绝对合法的。但是,模块化 jar 不能引用类路径上的非模块化 jar。自动模块(模块路径上的非模块化 jar)充当桥梁:模块化 jar 可以引用它们,而自动模块可以读取类路径。

标签: java classpath java-9 java-platform-module-system module-path


【解决方案1】:

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

依赖模块路径 ~> 类路径

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

由于一个模块必须要求它的所有依赖项,并且这些依赖项只能由其他命名模块(即类路径上的 JAR 不)来满足,因此模块化 JAR 的所有依赖项都必须放在模块路径上。是的,即使是非模块化的 JAR,也会变成 automatic modules

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

依赖类路径 ~> 模块路径

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

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

【讨论】:

  • Nicolai - 您的答案是正确的,但我认为可以扩展以指出可能需要 --add-modules 选项来确保解决类路径代码所需的模块。最初的问题询问为什么 javac 失败,我认为这是因为他/她正在编译类路径上的代码,并引用模块路径上的模块中的类,并且只需要 --add-modules 来确保模块得到解析。
  • 我认为 OP 正在尝试编译具有非模块化依赖项的模块化代码 - 无论哪种方式,我也添加了另一个方向,以确保。
  • @AlanBateman 我尝试在编译期间混合 -classpath 和 --module-path,即使我使用 --add-modules 也失败了。 javac -cp lib\* --module-path modules --add-modules simpleModule -d out @classes.txt 其中:lib-是我的 jar 文件夹,我想在未命名的模块中使用它; modules - 包含一个文件夹(文件夹名称 = simpleModule),其中包含 module-info.java; @classes.txt- 编译类列表(包括模块文件夹中的模块化类); simpleModule- 来自“模块”文件夹的模块名称。运行此命令后,我在libdir 中得到package does not exist for jar
  • @ZimboRodger 尝试引用lib/*,例如'lib/*'"lib/*"。如果这没有帮助,请提出一个新问题。
  • @Nicolai 没有帮助。提出问题stackoverflow.com/questions/49537980/…
【解决方案2】:

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

来自javac -help 消息和javac tools docs 的详细信息 -

--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” 和其他“未找到”错误。

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

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

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

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

如果显式模块 com.foo.app 中的代码引用公共类型 例如,在com.foo.bar 中,该类型的 签名指的是 输入仍在类路径中的 JAR 文件之一,然后输入代码 在com.foo.app 中将无法访问该类型,因为 com.foo.app 不能依赖未命名的模块。

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

【讨论】:

  • @MouseEvent 没错。我相信我之前错过了问题的那部分,只是回答了标题。编辑也包括在内。谢谢:)
猜你喜欢
  • 2018-09-07
  • 1970-01-01
  • 1970-01-01
  • 2012-10-26
  • 1970-01-01
  • 2011-04-17
  • 2012-01-17
  • 1970-01-01
  • 2016-06-04
相关资源
最近更新 更多