JAR 清单文件 - 规范和实现之间的差异更新

2022-09-02 13:20:26

我想将版本控制信息(可能还有一些关于jar的其他元数据)添加到我创建的库的jar中。但是,我不确定要使用什么属性。我发现规范以及文档都解释了可以有一个和一个(以及两者的标题和供应商)。但两者都不能正确解释规范和实现之间的区别。Specification-VersionImplementation-Version

我还看了不同的例子。

  • 文档中的那个使用人类可读的名称作为规范标题,使用包名称作为实现标题。点分隔的版本号用于规范版本,而简单的内部版本号用于实现版本。
  • gradle教程似乎只使用一个实现版本和一个人类可读的字符串作为实现标题
  • 在另一个问题中,我发现了一个示例,其中有多个用于不同包的实现版本。

这里的规范和实现元数据之间到底有什么区别?应如何使用这些不同的属性(尤其是版本号)?规范和实现的供应商不同有什么意义?

它甚至起到了我放在那里的作用吗?


答案 1

每个的含义在java.lang.Package的文档中进行了解释。

规范版本必须由 ASCII 数字序列组成,以 ASCII 句点分隔。不允许使用其他字符,句点不能位于值的开头或结尾,并且不允许使用连续的句点。

实现版本是一个自由格式的字符串。它可以具有任何格式。

规范版本始终与包相关联。如果为整个清单而不是特定程序包指定它,则它将应用于.jar文件中的所有程序包。

规范版本被许多 Java 技术用作解决依赖关系的一种手段。如果某个程序说它需要 JMF 库的 2.1 版或更高版本,一些 Java 环境将使用匹配的规范标题分析每个清单的规范版本中的数字,并确保在运行时类路径中提供正确的版本(并且没有其他版本)。

实际上,Package.isCompatibleWith 方法会进行这种检查。您甚至可以使用它来检查最低Java版本:

if (System.class.getPackage().isCompatibleWith("1.6")) {
    System.out.println("Running in Java 1.6 or later.");
}

更新

上述操作在 Java 9 模块化应用程序中不起作用。从 java.lang.Package 的文档:

为命名模块中的类自动定义的包具有以下属性:
...
• 规范和实现标题、版本和供应商未指定。

为未命名模块中的类自动定义的包具有以下属性:
...
• 规范和实现标题、版本和供应商未指定。

作为模块运行的 Java 9 程序应改用 ModuleDescriptor.version()。请注意,ModuleDescriptor.Version 类是可比较的:

Module libraryModule = SomeLibraryClass.class.getModule();
Optional<ModuleDescriptor.Version> libraryVersion =
    libraryModule.getDescriptor().version();

ModuleDescriptor.Version minimumRequiredVersion =
    ModuleDescriptor.Version.parse("2.0");

if (libraryVersion.isPresent() &&
    minimumRequiredVersion.compareTo(libraryVersion.get()) >= 0) {

    System.out.println(libraryModule + " is version " +
        minimumRequiredVersion + " or later.");
}

答案 2

好吧,规范是你的合同,例如:

  • 一个标准,如 JAXB、JDBC 或各种 Java EE 标准之一(例如 EJB 2.x、EJB 3.0、EJB 3.1)
  • 您的库、框架或服务的 API

实现是该规范的实现。

虽然规范的API(以及规范版本)可能不会更改,但随着您修复错误等,实现版本可能会发生变化。


推荐