简体   繁体   English

如何使用 Package 类的 getImplementationVersion() 方法从 JAR 的清单中获取包版本

[英]How to obtain a package version from the JAR's manifest, using the getImplementationVersion() method of the Package class

When I prepare my program for deployment, I pack it into a JAR, along with the Eclipse jar-in-jar class loader.当我准备要部署的程序时,我将它与 Eclipse jar-in-jar 类加载器一起打包到一个 JAR 中。 When my program runs from the JAR, I need to know a package's version, but I can not obtain it from the jar's manifest a simple and "honest" way.当我的程序从 JAR 运行时,我需要知道一个包的版本,但我无法从 jar 的清单中以一种简单而“诚实”的方式获取它。 The manifest looks like this:清单如下所示:

 Manifest-Version: 1.0
 Created-By: 1.8.0_73-b02 (Oracle Corporation)
 Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
 Rsrc-Main-Class: com.domain.sp2.controller.Controller
 Rsrc-Class-Path: ./ jar-in-jar-loader.zip javahelp-2.0.05.jar json-simple-1.1.1.jar
 Class-Path: .

 Name: com/domain/sp2/controller/
 Implementation-Version: 19

To obtain the package's implementation version, I try to use the simplest and straight-forward way:为了获取包的实现版本,我尝试使用最简单直接的方式:

package com.domain.sp2.controller;
public class Controller {
...
   public static String getBuildNumber() throws IOException {
     Package pckg = Controller.class.getPackage();
     pr(pckg.getName());    // prints "com.domain.sp2.controller", as expected 
     return pckg.getImplementationVersion();   // returns null
   }  
...
}

According to http://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html and http://docs.oracle.com/javase/8/docs/api/java/lang/Package.html#getImplementationVersion-- (and other sources), it should return "19", but it returns null.根据http://docs.oracle.com/javase/tutorial/deployment/jar/packageman.htmlhttp://docs.oracle.com/javase/8/docs/api/java/lang/Package.html# getImplementationVersion—— (和其他来源),它应该返回“19”,但它返回 null。 For the packages of the JRE libraries, it returns correct values.对于 JRE 库的包,它返回正确的值。 Perhaps I have missed a detail about how to name the package in the manifest, or the reason pertains to the JarRsrcLoader - may be it requires some special syntax to address packages.也许我错过了有关如何在清单中命名包的细节,或者原因与JarRsrcLoader - 可能是它需要一些特殊的语法来处理包。 I have also tried ".com/domain/..." , "/com/domain/..." and ".../controller" , and even "rsrc:./com/domain..." as the package name in the manifest - all without success.我也尝试过".com/domain/...""/com/domain/..."".../controller" ,甚至"rsrc:./com/domain..."作为清单中的包名称 - 都没有成功。 I could use other ways, eg to load the manifest as stream and parse it with the Manifest class, yet I would like to understand what is the correct way to use the getImplementationVersion() method.我可以使用其他方式,例如将清单加载为流并使用 Manifest 类对其进行解析,但我想了解使用getImplementationVersion()方法的正确方法是什么。

You can read the manifest file from the classLoader and get the value you need as below:您可以从 classLoader 读取清单文件并获取您需要的值,如下所示:

URLClassLoader cl = (URLClassLoader) YOUR_CLASS.class.getClassLoader();
try {
  URL url = cl.findResource("META-INF/MANIFEST.MF");
  Manifest manifest = new Manifest(url.openStream());
  Attributes mainAttributes = manifest.getMainAttributes();
  String implVersion = mainAttributes.getValue("Implementation-Version");

  System.out.println(implVersion);
} catch (IOException E) {
      // handle
}

Solved!解决了! At least for me :) You need to make sure, that the package in question is located only in one JAR and that JAR has the correct manifest.至少对我来说 :) 您需要确保有问题的包仅位于一个 JAR 中,并且 JAR 具有正确的清单。

Makes sense, since you query a package for a version and what should the JVM return, if that package is present in many JARs all with different or partially unset implementation versions?这是有道理的,因为您查询包的版本以及 JVM 应该返回什么,如果该包存在于许多具有不同或部分未设置实现版本的 JAR 中?

Please make sure you have a newline at the end of the manifest.请确保清单末尾有一个换行符。 If there is no newline character at the end, getImplementationVersion() will return null .如果末尾没有换行符, getImplementationVersion()将返回null

Reference : http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html参考: http : //docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html

I had the same issue in eclipse.我在日食中遇到了同样的问题。 The problem comes from the Eclipse jar-in-jar class loader.问题来自 Eclipse jar-in-jar 类加载器。 Simply put don't use the package your external libs in the jar method to generate the jar, use the extract external libs into your jar instead method and it should work.简单地说,不要使用 jar 方法中的外部库包来生成 jar,而是使用将外部库提取到 jar 中的方法,它应该可以工作。

I found this issue in my IDE (Eclipse) because the run from within the IDE wasn't using the generated Manifest in the jar.我在我的 IDE (Eclipse) 中发现了这个问题,因为从 IDE 中运行没有使用 jar 中生成的 Manifest。 To see the correct behavior, I just went to the command line of the computer to run the jar (since I had an appropriate main class set).为了查看正确的行为,我只是去计算机的命令行运行 jar(因为我有一个适当的主类集)。 But put another way, even if it doesn't work within the IDE, it should work in deployment.但换一种说法,即使它在 IDE 中不起作用,它也应该在部署中起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM