我可以通过MANIFEST.MF要求Java 9模块吗?

Hor*_*ux7 11 java java-platform-module-system java-9 java-module

我的Java库应该与Java 8和Java 9兼容.对于使用Java 9运行,我们需要一些Java 9模块.

我知道我可以通过命令行添加它--add-modules.但它是一个库,我无法控制命令行.

是否有一个等价--add-modulesMANIFEST.MF?或者还有其他与Java 8兼容的解决方案吗?

Zhe*_*lov 7

不幸的是,没有等价--add-modulesMANIFEST.MF.但是,您可以module-info.java在那里创建并声明您的依赖项:

module <module-name> {
    requires <dependency>;
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您编译module-info.java并简单地放入module-info.classJAR,它可能无法在某些平台上运行(例如Android).那么该怎么办?Java 9中有一个新功能:多版本JAR文件(JEP 238).我们的想法是,您可以将Java 9类文件放到特殊目录(META-INF/version/9/)中,Java 9将正确处理它们(而Java 8将忽略它们).

因此,这些是您应该执行的步骤:

  • 除了编译所有类module-info.javajavac --release 8
  • 编译module-info.java使用javac --release 9.
  • 构建一个JAR文件,使其具有以下结构:
JAR root
  - A.class
  - B.class
  - C.class
   ...
  - META-INF
    - versions
      - 9
        - module-info.class
Run Code Online (Sandbox Code Playgroud)

生成的JAR应与Java 8和Java 9兼容.

此外,您可以直接放入module-info.classMETA-INF文件夹.这将产生同样的效果.但是,这可能不适用于某些工具和平台.所以我认为第一种方式更可取.

  • 以上建议不正确.这里不需要创建多版本JAR文件.您可以将`module-info.class`文件放在JAR的根目录中.当JAR放在类路径上时,Java 8甚至Java 9将忽略该文件.当JAR放置在模块路径上时,Java 9将读取该文件,并解析它声明的任何依赖关系. (6认同)
  • @ Horcrux7是的,您的JAR必须包含在模块路径中.否则,Java将忽略`module-info`. (2认同)
  • @MarkReinhold你说得对,谢谢.我更新了我的答案. (2认同)

Nic*_*lai 5

模块在它们的模块声明中表达依赖关系,因此您必须创建一个module-info.java,定义模块的名称、依赖关系(在您的情况下使用requires java.activationrequires java.xml.bind和导出(稍后会详细介绍)。

模块声明必须由 Java 9 编译器编译以创建module-info.class属于 JAR 根文件夹的模块描述符。

Java 8 和 9

9 之前的 Java 版本将忽略module-info.class,这意味着如果您为 Java 8 编译其余代码(通过使用javac 8或使用新--release标志 on javac 9),您的库仍可在该版本上运行。

它会解决你的问题吗?

甚至 Java 9 也只会将您的 JAR 作为模块处理,如果它以模块路径结束。只有这样,它才会看到requires子句并在模块图中包含您正在使用的 Java EE 模块。这意味着在 Java 9 的类路径上使用您的库的客户端仍必须通过命令行手动添加这两个模块。

全模块化

如果您的模块用于模块路径,可访问性规则确保:

  1. 您的客户端只能在您导出的包中使用公共类型(在编译和运行时)
  2. 你的代码只能看到你依赖的模块

这意味着:

  1. 您必须在模块声明中包含导出
  2. 您必须声明所有依赖项,而不仅仅是在两个 JDK 模块上

特别是如果您依赖尚未模块化的项目,第二点可能会很困难,但这是另一个问题。