ams*_*ams 33 java java-platform-module-system java-9
Java 9有三种方法可以将编译后的代码打包到文件中:
JIMAGE针对速度和空间进行了优化,并在运行时由JVM使用,因此有理由引入JIMAGE.JIMAGE文件不应发布到maven repos或在编译或链接时使用.
文档声称JMOD可以存储本机代码和JAR文件无法存储的其他内容,开发人员可以制作和分发自己的JMOD文件.JDK附带jmods/包含JDK 所有模块的目录,供用户依赖.
问题:
con*_*ion 33
JMOD 的用途没有很好的文档记录,现有文档相当稀少。这是对系统的深入解释,根据我的理解。
警告:此答案的部分内容相当长、冗长、部分冗余且难以阅读。非常欢迎建设性、结构性或语法性的编辑,以提高未来读者的可读性。
Java 9 的新模块系统Project Jigsaw引入了新的可选链接时间阶段的概念,当使用 CLI 工具jlink构建自定义空间优化的 JRE时会发生这种情况。jlink将所有显式/可传递 JAR 模块/JMOD 依赖项捆绑到一个缩小的 JRE 中;依赖图中的所有其他无法访问的依赖项(从指定的根模块开始)都不会捆绑到构建的 JRE 中。从 JDK 9+ 开始,Java 的所有标准库都已分解为 JMOD,位于<jdk>/jmods.
JAR 只能包含.class资源文件,而 JMOD(即.jmod文件)包含额外的文件,这些文件专门在新的可选链接时间阶段使用以自定义 JRE(例如,可执行文件、本机库、配置、合法许可证等)。这些附加文件在运行时不能作为类路径中的资源使用,而是安装在构建的 JRE 中的不同位置下(例如,可执行文件和本机库放在 下<jre>/bin)。从相关的捆绑 JAR 和 JMOD 依赖项中,类和文件资源将被写入单个优化的 JIMAGE 文件,位于<jre>/lib/modules(<jre>/lib/rt.jar在 Java 8 和以前的版本中替换)。JMOD 的作用是在编译时和链接时,而不是 设计为在运行时使用。
对于一般的库/应用程序,只需要构建和推送 JAR,而不是 JMOD;只有在特定条件下,JMOD 才会提供链接时间阶段所需的关键功能。在撰写本文时,Maven 似乎没有为 alpha 版本插件之外的 JMOD 提供强大的支持org.apache.maven.plugins:maven-jmod-plugin。
这个冗长的答案动机更复杂,并揭示了新模块系统的基本运作方式。整篇文章都非常强调 CLI 工具jlink,因为 JMOD 是专门为该工具引入的这个新的可选链接时间阶段而设计的。
Java 9在“ JEP 261:模块系统”中引入了Project Jigsaw,这是一种新颖的模块系统,可用于最小化启动时间和 JRE 的大小。作为此版本的一部分,CLI 实用程序、和以及 JMODs/ s(基于 ZIP)和 JIMAGEs/ s 的新文件格式一起被引入。jmodjimagejlink.jmod.jimage
这个新模块系统的一个重要收获是,CLI 工具jlink使开发人员能够构建一个自定义 JRE,其中仅包含与其应用程序相关的标准库和外部依赖项。这在管道中的传统阶段之间引入了可选链接时间阶段的新概念compile time -> run time。
举一个使用 优势的例子jlink,一个从 JDK 15 构建的极简 JRE 的java.base大小约为 40MB,与 JDK 15 的约 310MB 大小形成鲜明对比。这对于传送最小的自定义 JRE 尤其有用,例如用于精益 Docker 映像。新的模块系统为 Java 生态系统带来了显着的好处,这些好处已经在别处详细讨论过,因此这里不再详细阐述。
JARs、JMODs 和 JIMAGEs 的高级描述并不能很快提供一种强烈区分三种文件格式角色的解释。以下是对每个目的的非详尽概述:
JAR:基于 ZIP 文件格式的经典格式,用于在运行时将类和资源捆绑到类路径中。这是自 1997 年 JDK 1.1 以来制定的事实上的主流标准。可以使用java -cp/-classpath标志将 JAR 添加到类路径中。几乎每一个图书馆或依赖有,是,和将要使用这种格式,所以在这一部分掩盖了。
JMOD:一种基于 ZIP 文件格式的新格式,用于捆绑 JAR 可以包含的相同内容,但支持在可选链接时使用的其他文件(例如可执行文件、本机库、配置、合法许可证等)构建自定义 JRE 时的阶段。JMOD 旨在在编译时和链接时使用,但不能在运行时使用。很可能引入了这种新格式(而不是扩展 JAR),因为这种新的基于归档格式的目录具有特殊含义,该格式与已经使用相同目录名称的 JAR不向后兼容。
module-info.class使用 CLI 工具从 JAR 模块(即包含有效的)构建 JMOD jmod。<jdk>/jmods在 JDK 安装中。java -cp/-classpath标志在类路径中使用,因为 JMOD 存档中的类和资源存储在classes存档根目录下而不是在存档根目录中。注意:可能有一种方法可以在运行时轻松地将 JMOD 添加到类路径中;然而,研究并未明确说明与此相关的任何功能。仅向类路径添加 JMOD 不足以使用类和资源。
ClassLoader但是,可以使用自定义来在运行时正确解析 JMOD 存档中的类和资源文件;这通常是不推荐的,也不是 JMOD 的目的。
<jre>/lib/rt.jar; 它已被删除,取而代之的是存储在<jre>/lib/modules. 此格式不是基于 ZIP 格式,而是使用自定义格式,与原始遗留 JAR 格式相比,这种格式在时间和空间方面的效率显着提高,从而减少了启动时间。
jlink,所有相关(显式或传递性)模块依赖项的类和资源(来自 JAR 模块或 JMOD)都被编译为单个优化的 JIMAGE 文件(同样,存储在 下<jre>/lib/modules)。jimage。例如jimage list $JAVA_HOME/lib/modules如前所述,CLI 工具jlink在普通 Java 管道中引入了一个新的可选阶段 -链接时间阶段。此链接时间阶段用于从一组 Java 9 模块(带有module-info.java描述符的 JAR或 JMOD)生成自定义构建的 JRE 。
高级阶段简要描述如下:
编译时间(javac):如javac文档所述,编译时间阶段...
...读取用 Java 编程语言编写的类和接口定义,并将它们编译成字节码类文件。它还可以处理 Java 源文件和类中的注释。
链接时间( jlink):如“ JEP 282: jlink: The Java Linker ”中所述,链接时间阶段是...
...编译时(javac 命令)和运行时(java 运行时启动器)阶段之间的可选阶段。链接时需要一个链接工具,该工具将组装和优化一组模块及其传递依赖项,以创建运行时映像或可执行文件。
链接时间是进行全局优化的机会,否则在编译时很难或在运行时代价高昂。一个例子是当所有输入变为常数(即,不是未知的)时优化计算。后续优化将删除不再可访问的代码。
运行时(java):如javac文档中所述,运行时阶段...
...启动 Java 应用程序。它通过启动 Java 运行时环境 (JRE)、加载指定的类并调用该类的 main() 方法来完成此操作。
在链接时间阶段,模块(有效的 JAR 模块或形式 JMODs' classes)中的所有类和资源都被编译为位于 的单个优化 JIMAGE 运行时映像<jre>/lib/modules。未明确或传递包含的模块将不会包含在此最终 JIMAGE 中,从而节省了大量空间。但是,在构建自定义 JRE 时,JRE 内部可能需要一些其他文件;例如可执行命令或本机库。对于 JAR 模块,故事到此结束——JAR 无法毫无歧义地将文件(超出 JIMAGE 中包含的类)添加到构建的 JRE 中。
JMOD 简介:JMOD 能够将附加文件添加到自定义构建的 JRE 中;一些示例(但不一定详尽):可执行命令、配置文件、头文件、法律声明和许可证、本机库和手册页。这允许模块依赖以自己的方式塑造构建的 JRE。jlink下一节将介绍 CLI 工具如何将这些附加文件插入到构建的 JRE 中的行为。
JMOD仅用于编译时间和链接时间阶段,如“ JEP 261:模块系统”中所述:
JMOD 文件可以在编译时和链接时使用,但不能在运行时使用。要在运行时支持它们,通常需要我们准备好即时提取和链接本机代码库。这在大多数平台上都是可行的,尽管它可能非常棘手,而且我们还没有看到很多需要此功能的用例,因此为简单起见,我们选择在此版本中限制 JMOD 文件的实用性。
一个很好的问题可能是“为什么不启用 JAR 来添加链接时行为?”。这里有一个偷偷摸摸的怀疑,这不能为现有的 JAR 和工具提供足够的向后兼容性支持。JAR 归档文件格式中没有保留文件名的规范。如果现有库在用于链接时的目录下存储任何资源,jlink无法准确猜测它是在链接时消耗还是在运行时需要。具有保留目录名称的新文件格式规范将解决此冲突问题 - 例如新的 JMOD 格式。使用 JMOD,对于链接时间和运行时间指定哪些资源没有歧义。此外,还可以扩展 JMOD 格式以在更高版本的 JDK 中添加新功能,而不会出现向后兼容性问题。
JMOD 文件格式类似于 JAR,因为它基于 ZIP 文件格式。JMOD 文件具有以下保留目录名称和以下行为(这不一定是详尽的列表!):
bin( --cmds): 复制到的可执行命令<jre>/binclasses( --class-path): 用于包含到最终构建的 JIMAGE 中,存储在`/lib/modulesconf( --config): 附加配置复制到<jre>/conf; 如果需要,可能用于控制任何捆绑模块的配置include( --header-files): 附加的 C 头文件,这些文件被复制到<jre>/include/使用 JNI 为 JVM 构建 C 库;例如在java.base,JNI 接口被导出legal( --legal-notices):复制到的模块的法律声明和许可证<jre>/legal/<module name>/lib( --libs): 复制到的本地库<jre>/bin对于奇怪的倾向,
$JAVA_HOME/jmods可以使用任何读取 ZIP 档案的应用程序检查标准库 JMOD(位于JDK 9+ 下)。
JMOD 没有被迅速采用并且文档可用性较差的一个重要原因是,简而言之,对于绝大多数库和模块依赖项而言,它们不是必需的。虽然它们对于特定用例仍然有用,但模块应该使用已经得到主流支持的 JAR 格式,因为它是在 1997 年的 JDK 1.1 中定义的(module-info.java在 2017 年的 JDK 9 中添加了模块支持)。
从 CLI 工具的文档中jmod:
对于大多数开发任务,包括在模块路径上部署模块或将它们发布到 Maven 存储库,请继续将模块打包到模块化 JAR 文件中。jmod 工具适用于具有本机库或其他配置文件的模块,或者您打算使用 jlink 工具链接到运行时映像的模块。
观点:至少在很长一段时间内,JMOD 可能不会被开发人员大量采用。大多数开发人员永远不会听到或知道 JMOD 的用途——他们也不需要。JMOD 在构建 JRE 的幕后发挥着重要作用(所有 Java 标准库模块都是 JMOD),但由于它们在链接时的特殊用例,因此不会影响绝大多数应用程序和项目。Java 9 于 2017 年发布,Java 生态系统中的依赖项仍然难以可靠地拥有一个module-info.class描述符来使 JAR 成为有效的成熟模块......
jlink支持使用附加文件自定义自定义构建的 JRE。jlink,因此没有必要发布仅包含类和资源的 JMOD。生态系统支持和工具不一定会在短期内采用 JMOD,并且在未来几年肯定会出现兼容性问题。在撰写此答案时,关于 Java 9 及更高版本的 JMOD 用途的文档很少。事实上,Google 搜索短语“java jmods”和“jmod format”带来了与第二个搜索结果相同的 StackOverflow 问题。因此,有些方面可能无法准确解释,但一般是“方向正确”的;此外,它可能无法描绘全貌。如果您发现任何问题或警告,请发表评论,我会尝试将其与此答案相协调。
Mic*_*ter 10
以下是JEP 261:模块系统的一些引用,其中包含有关JMOD文件的部分.
为什么?
从JEP 261:
新的JMOD格式超出了JAR文件,包括本机代码,配置文件和其他类型的数据,这些数据自然不适合JAR文件(如果有的话).
和
JMOD文件的最终格式是一个开放的问题,但现在它基于ZIP文件.
开发人员应该发布JMOD文件吗?
请注意,JMOD文件似乎是在编译时和链接时合并本机代码(以及其他内容)的一种方法.从JEP 261:
JMOD文件可以在编译时和链接时使用,但不能在运行时使用.
(说实话,我不确定在JDK 9之前如何发布本机代码.)对于绝大多数开发人员(没有本机库或其他角落案例),我们只会发布模块化jar.
| 归档时间: |
|
| 查看次数: |
8099 次 |
| 最近记录: |