How to obtain a package version from the JAR's manifest, using the getImplementationVersion() method of the Package class
Solution 1
You can read the manifest file from the classLoader and get the value you need as below:
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
}
Solution 2
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.
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?
Solution 3
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
.
Reference : http://docs.oracle.com/javase/7/docs/technotes/guides/jar/jar.html
Solution 4
I had the same issue in eclipse. The problem comes from the Eclipse jar-in-jar class loader. 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.
Related videos on Youtube
Comments
-
m. vokhm about 1 year
When I prepare my program for deployment, I pack it into a JAR, along with the Eclipse jar-in-jar class loader. 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. 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. For the packages of the JRE libraries, it returns correct values. 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. 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. I could use other ways, e.g. 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 thegetImplementationVersion()
method. -
m. vokhm over 7 yearsYes, I can read the manifest (as I mentioned in the question), but I would like to know about the getImplementationVersion() method. Why It won't work properly for me? Thank you for the response, nevertheless.
-
m. vokhm over 7 yearsYes, thank you. The manifest is made by Ant, yet I have checked it - the newline is present, even two of them :)
-
m. vokhm almost 6 yearsYet I can't understand what's wrong with my JAR/code. The package is only in one jar (it's a single JAR in my case). Manifest looks OK, at least I see nothing bad there (it's cited in the original post). Nevertheless
getName()
returns the right name, and thegetImplementationVersion()
returnsnull
. Java 7 and 8, x32 and x64, Windows. -
HelloWorld almost 5 years@m.vokhm regarding why it does not work maybe because the manifest does not have the info you want. If I do
Enumeration<URL> resources = MainApp.class.getClassLoader() .getResources("META-INF/MANIFEST.MF");
and loop through the elements I only get Java's official Manifests (I don't know how to name them) like for the first one retrieved :jar:file:/usr/share/java/java-atk-wrapper.jar!/META-INF/MANIFEST.MF
. And if I open this manifest, there is noImplementation-Version
field. This came to me after looking at thePackage
private constructor which takes aManifest
. -
HelloWorld almost 5 years@m.vokhm Now that I could get I working, I understand better how it works. Did you try
getImplementationVersion
from IDE or from generated jar ? Because from IDE there is no Manifest (sogetImplementationVersion
will return null), you'll get it only 'as soon as you launch the real jar'. This jar has a Manifest and depending on how you generated your jar it may contain the version otherwise you'll still get null (but you can add it in this case)