Java读取Jar包MANIFEST.MF版本属性返回null问题求助
问题原因
- 调用
getClass().getPackage().getImplementationVersion()返回null的核心原因是:当类未从Jar包加载(比如IDE直接运行class文件)、或者类加载器无法匹配到对应Jar包的元数据时,就会返回空值。Java 11+模块化场景下如果包未正确导出也可能触发该问题。 - 直接读取
/META-INF/MANIFEST.MF拿到错误内容的原因是:ClassPath下存在多个Jar包的META-INF/MANIFEST.MF文件,类加载器默认返回搜索顺序中第一个匹配的文件,你拿到的是系统类库的Manifest,不是自己业务Jar的。 - 额外错误点:不要用
Properties类加载Manifest文件,Manifest有特殊的格式规范(比如行超长自动折叠、键值对的空格要求等),和Properties的解析规则不兼容,即使拿到正确的文件流也可能解析失败。
解决方案
通过当前类的代码源定位到自身所在的Jar包,再使用JDK内置的java.util.jar.Manifest类解析清单文件,代码如下:
import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.jar.Attributes; import java.util.jar.Manifest; public class VersionUtil { public static String getImplementationVersion() { // 替换为你自己业务Jar中任意一个存在的类,确保是从你自己的Jar加载的 Class<?> clazz = VersionUtil.class; String className = clazz.getSimpleName() + ".class"; URL classUrl = clazz.getResource(className); if (classUrl == null) { return null; } String classPath = classUrl.toString(); // 判断是否从Jar包加载 if (!classPath.startsWith("jar:")) { // 未打包成Jar,比如IDE直接运行,返回空即可 return null; } // 提取Jar包的路径 String jarPath = classPath.substring(0, classPath.lastIndexOf("!/") + 2); try (InputStream manifestIs = new URL(jarPath + "META-INF/MANIFEST.MF").openStream()) { Manifest manifest = new Manifest(manifestIs); Attributes attr = manifest.getMainAttributes(); return attr.getValue("Implementation-Version"); } catch (IOException e) { // 异常处理可根据自己的业务调整 e.printStackTrace(); return null; } } public static void main(String[] args) { String swVersion = getImplementationVersion(); System.out.println(swVersion); } }
注意事项
- 代码中
clazz必须替换为你自己业务Jar内的类,不要用JDK内置类或者第三方依赖的类,否则定位到的会是其他Jar包。 - 只有打包成Jar包运行时才能拿到版本号,IDE中直接运行未打包的class文件时返回null属于正常现象,打包后运行即可正常输出
1.1.3-b000。
内容的提问来源于stack exchange,提问作者lmattcris
相关产品推荐
相关产品推荐

