Retrieve Jar Version

获取 Jar 包版本号

背景

在运行时获取当前 Jar 包的版本信息是很常见的诉求,用于观测等场景。常见的方案包括读 maven 的 pom 文件和反射两种方式。

方案

读 maven pom 文件

此方案的原理是,maven 在打包时会在 jar 包下创建一个命名为 META-INF/maven.$groupId.$artifactId/pom.properties property 文件,以 netty 为例,存在如下文件,文件名为 META-INF/maven.io.netty.netty.properties/pom.properties

1
2
3
version=3.7.0.Final
groupId=io.netty
artifactId=netty

在代码中从 classpath 中读取该 Properties 文件,代码来自 StackOverflow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
String path = "META-INF/maven.io.netty.netty/pom.properties";

Properties prop = new Properties();
InputStream in = ClassLoader.getSystemResourceAsStream(path );
try {
prop.load(in);
}
catch (Exception e) {

} finally {
try { in.close(); }
catch (Exception ex){}
}
System.out.println("maven properties " + prop);

反射

通过 Foo.class.getPackage()#getSpecificationVersion 方法获取类所在 jar 包的版本。本方法要求 jar 包中包含 Manifest 文件。具体做法如下。

  1. 在 maven 打包过程中,向 Manifest 文件中写入 Version
  2. 在需要获取版本的地方,使用反射获取版本号

maven 打包写入版本号

在 maven 的 pom.xml 文件加入如下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>

使用反射获取版本号

如下图的 getVersion 方法获取给定 class 的 jar 包版本

1
2
3
public static String getVersion(Class clazz) {
return clazz.getPackage().getSpecificationVersion();
}

方案对比

  1. 方案一 maven 的实现,不需要 jar 包提供方额外做什么事情,但是其他 build 方式不支持
  2. 方案二是 java 官方的实现,需要 jar 包提供方提供 Manifest 文件,但是版本本身是强依赖、获取方式简单,个人推荐这种方式

参考

  1. Maven Archiver Manifest
  2. Setting Package Version Information