Java jar version checking

How to find version of Jar if not mentioned in Manifest

I have a project in which many JARS are checked in but there is no version information for them. I have to implement dependency management using Apache Ivy, but I don’t know which versions to point to in my ivy.xml . I checked the Manifests and many of them do not have the JAR versions mentioned there. Is there another way to find version of JARS? I understand that finding checksum and comparing them is another option but for that I need to check each of my JAR against checksums of all possible JAR versions and so that is not an option. Any other suggestions please?

2 Answers 2

I would say — there’s no other way. If you have somewhere all the jar versions (of the library in question), you can e.g. md5 them and then compare with the md5 sum of that unknown jar version you have. I might be wrong but I don’t see any other way.

search.maven.org lists the md5 hashes of all of the jars in maven central. They’re not all in one place, but you could probably write a script to gather up all of the version/md5 info for a particular jar.

To add to some previous comments, you can find details about the Maven REST API at http://search.maven.org/#api. The URL of interest to you here is http://search.maven.org/solrsearch/select?q=1:»SHA-1 checksum».

Читайте также:  Php function with html form

I had a case where I needed to find the versions of hundreds of JARs as part of a Java application and did so from 2 sources. First I cracked open the JAR and checked the Manifest.MF file for the JAR version first in the field ‘Implementation-Version’ and if not there, then ‘Bundle-Version’. The code I used for that is below (obviously you will want some better error handling):

public String getVersionFromJarManifest(File jarFile) < try < Manifest manifest = new JarFile(jarFile).getManifest(); Attributes mainAttribs = manifest.getMainAttributes(); String version = mainAttribs.getValue("Implementation-Version"); if(version == null || version == "" || version.isEmpty())< version = mainAttribs.getValue("Bundle-Version"); >return version; > catch (Exception e) < LOGGER.warn("Manifest not found for <>", jarFile.getPath()); return null; > > 

If I was unable to to get the version from the Manifest file then I computed a SHA-1 checksum of the JAR and searched Maven for it. That code (with again not great error checking) is below:

public String getVersionFromMavenByChecksum(File jarFile) < String sha = null; try < MessageDigest md = MessageDigest.getInstance("SHA1"); FileInputStream fis = new FileInputStream(jarFile); byte[] dataBytes = new byte[1024]; int nread = 0; while ((nread = fis.read(dataBytes)) != -1) < md.update(dataBytes, 0, nread); >byte[] mdbytes = md.digest(); //convert the byte to hex format StringBuffer sb = new StringBuffer(""); for (int i = 0; i < mdbytes.length; i++) < sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); >sha = sb.toString(); > catch (Exception e) < LOGGER.warn("ERROR processing SHA-1 value for <>", jarFile.getPath()); return null; > return getVersionBySha(sha); > public String getVersionBySha(String sha) < String version = null; CloseableHttpClient httpClient = HttpClients.createDefault(); ListsuQueryParams = new ArrayList<>(); suQueryParams.add(new BasicNameValuePair("q", "1: \"" + sha + "\"")); String result = null; try < result = MavenApiUtil.apiGETCall("http://search.maven.org/solrsearch/select", suQueryParams, null, httpClient); >catch (Exception e)< LOGGER.warn("ERROR querying Maven for version for SHA <>", sha); return null; > //Parse response return version; > 

Источник

Читайте также:  Required validation in html

How to Get the Version Number of a JAR File

The preferred mechanism for storing version information is to use the Manifest file. There are two keywords commonly used to store version information in the manifest: «Implementation-Version» and «Bundle-Version». Here’s a simple script you can use to find the version number in the Manifest:

java.io.File file = new java.io.File("/drivers/h2/h2-1.3.162.jar"); java.util.jar.JarFile jar = new java.util.jar.JarFile(file); java.util.jar.Manifest manifest = jar.getManifest(); String versionNumber = ""; java.util.jar.Attributes attributes = manifest.getMainAttributes(); if (attributes!=null) < java.util.Iterator it = attributes.keySet().iterator(); while (it.hasNext())< java.util.jar.Attributes.Name key = (java.util.jar.Attributes.Name) it.next(); String keyword = key.toString(); if (keyword.equals("Implementation-Version") || keyword.equals("Bundle-Version"))< versionNumber = (String) attributes.get(key); break; >> > jar.close(); System.out.println("Version: " + versionNumber); //"Version: 1.3.162"

Parsing the File Name

If, for whatever reason, the version information is not found in the manifest, you can try to parse the jar file name. This is extremely error prone but sometimes its your only option. Here’s a simple script to extract the version number from the file name.

java.io.File file = new java.io.File("/drivers/h2/h2-1.3.162.jar"); String versionNumber = ""; String fileName = file.getName().substring(0, file.getName().lastIndexOf(".")); if (fileName.contains("."))< String majorVersion = fileName.substring(0, fileName.indexOf(".")); String minorVersion = fileName.substring(fileName.indexOf(".")); int delimiter = majorVersion.lastIndexOf("-"); if (majorVersion.indexOf("_")>delimiter) delimiter = majorVersion.indexOf("_"); majorVersion = majorVersion.substring(delimiter+1, fileName.indexOf(".")); versionNumber = majorVersion + minorVersion; > System.out.println("Version: " + versionNumber); //"Version: 1.3.162"

javaxt.io.Jar

Note that the javaxt.io.Jar class can be used to return the version of a jar file with one simple call. The getVersion() method combines both techniques described here into one method. Example:

System.out.println("Version: " + new javaxt.io.Jar(file).getVersion());

Источник

how to check the version of jar file?

I am currently working on a J2ME polish application, just enhancing it. I am finding difficulties to get the exact version of the jar file. Is there any way to find the version of the jar file for the imports done in the class? I mean if you have some thing, import x.y.z; can we know the version of the jar x.y package belongs to?

17 Answers 17

Decompress the JAR file and look for the manifest file ( META-INF\MANIFEST.MF ). The manifest file of JAR file might contain a version number (but not always a version is specified).

As i told that I am working on enhancing the application, I have downloaded the jar files and I know the version of the jar files. But I wanted to know the version of the jar which the package belongs to, I hope you get it.

To explain you more, I have import x.y.z, I know that x.y belongs to a-4.1.jar, but the application which i am working has been developed long back, and I dono what version of a.jar file have they used, I am worried about the version because, some of the classes have been depreciated from the jar of the older version (I feel so), because, even though I have jar in the library, I find the import cannot be resolved

So is it that, if you know the version of jar which they used while building the application, you would also use the same version of jar to execute the application?

If that is what your requirement is, then am afraid that you will have to rebuild the application with exclusion of deprecated jars. Because finding version number associated with a given jar is like one to one function. Only one version number for one jar file. But finding which version of jar was used at the time of development of application sounds highly impossible to me unless the developer attaches the required jars with the application.

Recording version in MANIFEST.MF appears to be optional. There’s no version recorded in various sqljdbc42.jar files that I’ve used with Cognos, yet Cognos is able to report a version (4.2.6420.100). Where is it getting this version from if it’s not recorded in the manifest?

You need to unzip it and check its META-INF/MANIFEST.MF file, e.g.

unzip -p file.jar META-INF/MANIFEST.MF 

Just to expand on the answers above, inside the META-INF/MANIFEST.MF file in the JAR, you will likely see a line: Manifest-Version: 1.0 ← This is NOT the jar versions number!

You need to look for Implementation-Version which, if present, is a free-text string so entirely up to the JAR’s author as to what you’ll find in there. See also Oracle docs and Package Version specificaion

Just to complete the above answer.

Manifest file is located inside jar at META-INF\MANIFEST.MF path.

You can examine jar’s contents in any archiver that supports zip.

Each jar version has a unique checksum. You can calculate the checksum for you jar (that had no version info) and compare it with the different versions of the jar. We can also search a jar using checksum.

Basically you should use the java.lang.Package class which use the classloader to give you informations about your classes.

String.class.getPackage().getImplementationVersion(); Package.getPackage(this).getImplementationVersion(); Package.getPackage("java.lang.String").getImplementationVersion(); 

I think logback is known to use this feature to trace the JAR name/version of each class in its produced stacktraces.

Thought I would give a more recent answer as this question still comes up pretty high on searches.

Run the following on the CLi jar file:

unzip -p jenkins-cli.jar META-INF/MANIFEST.MF 
Manifest-Version: 1.0 Built-By: kohsuke Jenkins-CLI-Version: 2.210  

The CLi version is listed above.

To get the Server Version, run the following:

java -jar ./jenkins-cli.jar -s https:// -auth @.com: version 

(the above will vary based on your implementation of authentication, please change accordingly)

Dec 23, 2019 4:42:55 PM org.apache.sshd.common.util.security.AbstractSecurityProviderRegistrar getOrCreateProvider INFO: getOrCreateProvider(EdDSA) created instance of net.i2p.crypto.eddsa.EdDSASecurityProvider 2.210  

This simple program will list all the cases for version of jar namely

  • Version found in Manifest file
  • No version found in Manifest and even from jar name
  • Manifest file not found
Map jarsWithVersionFound = new LinkedHashMap(); List jarsWithNoManifest = new LinkedList(); List jarsWithNoVersionFound = new LinkedList(); //loop through the files in lib folder //pick a jar one by one and getVersion() //print in console..save to file(?)..maybe later File[] files = new File("path_to_jar_folder").listFiles(); for(File file : files) < String fileName = file.getName(); try < String jarVersion = new Jar(file).getVersion(); if(jarVersion == null) jarsWithNoVersionFound.add(fileName); else jarsWithVersionFound.put(fileName, jarVersion); >catch(Exception ex) < jarsWithNoManifest.add(fileName); >> System.out.println("******* JARs with versions found *******"); for(Entry jarName : jarsWithVersionFound.entrySet()) System.out.println(jarName.getKey() + " : " + jarName.getValue()); System.out.println("\n \n ******* JARs with no versions found *******"); for(String jarName : jarsWithNoVersionFound) System.out.println(jarName); System.out.println("\n \n ******* JARs with no manifest found *******"); for(String jarName : jarsWithNoManifest) System.out.println(jarName); 

Источник

Can I determine the version of a Java library at runtime?

Third party Java library means a Jar file, and the Jar file manifest has properties specifically to specify the version of the library.

Beware: Not all Jar files actually specify the version, even though they should.

Built-in Java way to read that information is to use reflection, but you need to know some class in the library to query. Doesn't really matter which class/interface.

public class Test < public static void main(String[] args) < printVersion(org.apache.http.client.HttpClient.class); printVersion(com.fasterxml.jackson.databind.ObjectMapper.class); printVersion(com.google.gson.Gson.class); >public static void printVersion(Class clazz) < Package p = clazz.getPackage(); System.out.printf("%s%n Title: %s%n Version: %s%n Vendor: %s%n", clazz.getName(), p.getImplementationTitle(), p.getImplementationVersion(), p.getImplementationVendor()); >> 
org.apache.http.client.HttpClient Title: HttpComponents Apache HttpClient Version: 4.3.6 Vendor: The Apache Software Foundation com.fasterxml.jackson.databind.ObjectMapper Title: jackson-databind Version: 2.7.0 Vendor: FasterXML com.google.gson.Gson Title: null Version: null Vendor: null 

You're right, this is the more standard way. However, the Maven way is enforced by the keepers of the major repositories, so it's more reliable. Ideally, I guess I'd combine the approaches.

This does not work properly if two jars contain the same package. Example: a-1.1.1.jar contains class com.abc.A and b-2.2.2.jar contains com.abc.B. Then the output for the package com.abc is the same for classes A and B.

Although there is no universal standard, there is a hack that works for most open source libraries, or anything that is released through a Maven repository through the Maven Release Plugin or compatible mechanisms. Since most other build systems on the JVM are Maven compatible, this should apply to libraries distributed through Gradle or Ivy as well (and possibly others).

The Maven release plugin (and all compatible processes) create a file in the released Jar called META-INF/$.$/pom.properties , which contains the properties groupId , artifactId and version .

By checking for this file and parsing it, we can detect the versions of a majority of library versions out there. Example code (Java 8 or higher):

/** * Reads a library's version if the library contains a Maven pom.properties * file. You probably want to cache the output or write it to a constant. * * @param referenceClass any class from the library to check * @return an Optional containing the version String, if present */ public static Optional extractVersion( final Class referenceClass) < return Optional.ofNullable(referenceClass) .map(cls ->unthrow(cls::getProtectionDomain)) .map(ProtectionDomain::getCodeSource) .map(CodeSource::getLocation) .map(url -> unthrow(url::openStream)) .map(is -> unthrow(() -> new JarInputStream(is))) .map(jis -> readPomProperties(jis, referenceClass)) .map(props -> props.getProperty("version")); > /** * Locate the pom.properties file in the Jar, if present, and return a * Properties object representing the properties in that file. * * @param jarInputStream the jar stream to read from * @param referenceClass the reference class, whose ClassLoader we'll be * using * @return the Properties object, if present, otherwise null */ private static Properties readPomProperties( final JarInputStream jarInputStream, final Class referenceClass) < try < JarEntry jarEntry; while ((jarEntry = jarInputStream.getNextJarEntry()) != null) < String entryName = jarEntry.getName(); if (entryName.startsWith("META-INF") && entryName.endsWith("pom.properties")) < Properties properties = new Properties(); ClassLoader classLoader = referenceClass.getClassLoader(); properties.load(classLoader.getResourceAsStream(entryName)); return properties; >> > catch (IOException ignored) < >return null; > /** * Wrap a Callable with code that returns null when an exception occurs, so * it can be used in an Optional.map() chain. */ private static T unthrow(final Callable code) < try < return code.call(); >catch (Exception ignored) < return null; >> 

To test this code, I'll try 3 classes, one from VAVR, one from Guava, and one from the JDK.

public static void main(String[] args)
Optional[0.9.2] Optional[24.1-jre] Optional.empty 

Источник

Оцените статью