使用Ant创建嵌套Jar后,Manifest内容与Java返回结果不一致
排查Ant打包Jar时Manifest内容不一致的问题
我之前也碰到过类似的情况,Manifest解压后看到的内容和Java代码读取的有差异,大概率是这几个细节没处理好,咱们一步步来排查:
1. 编码不一致导致的显示差异
Ant默认会用系统编码来写入Manifest文件,但Java读取Manifest时默认采用UTF-8编码,如果两者编码不匹配,就会出现内容乱码或者属性值截断的情况。
解决办法:在Ant的<manifest>标签里显式指定UTF-8编码,确保写入和读取的编码一致:
<manifest merge="false" encoding="UTF-8"> <!-- 你的属性定义 --> </manifest>
2. Ant的Manifest合并逻辑干扰
如果你的项目依赖的Jar包自带Manifest文件,Ant默认会把这些Manifest和你自定义的合并在一起,导致解压后看到的是合并后的内容,但Java代码读取的可能是主Manifest的部分属性(或者反过来)。
解决办法:关闭Manifest合并功能,只使用你自定义的内容:
<manifest merge="false" encoding="UTF-8"> <!-- 仅保留你需要的属性 --> </manifest>
3. Jar-in-Jar Loader的特殊属性处理
你用的是JarRsrcLoader实现Jar包嵌套,这个工具对Manifest有特定要求,比如必须正确设置Rsrc-Class-Path来指定内部依赖Jar的路径,如果你的Ant脚本里这个属性没写全或者格式错误,Java代码读取时可能会解析出异常内容。
给你补全一个正确的Ant脚本片段,包含Jar-in-Jar所需的完整配置:
<target name="create_run_jar"> <tstamp><format property="buildTime" pattern="yyyy/MM/dd hh:mm:ss"/></tstamp> <jar destfile="${dir.jarfile}/MyJar.jar"> <!-- 关闭合并+指定UTF-8编码 --> <manifest merge="false" encoding="UTF-8"> <attribute name="Main-Class" value="org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader"/> <attribute name="Rsrc-Main-Class" value="com.qantas.Converter"/> <attribute name="Class-Path" value="."/> <!-- 必须指定内部依赖Jar的路径,多个用空格分隔 --> <attribute name="Rsrc-Class-Path" value="./lib/dep1.jar ./lib/dep2.jar"/> <attribute name="Built-Time" value="${buildTime}"/> </manifest> <!-- 打包你的项目类文件 --> <fileset dir="${dir.classes}"/> <!-- 将依赖Jar包嵌套到主Jar的lib目录下 --> <zipfileset src="${dir.lib}/dep1.jar" prefix="lib"/> <zipfileset src="${dir.lib}/dep2.jar" prefix="lib"/> </jar> </target>
4. 用正确的Java代码读取Manifest
确保你读取的是主Jar的Manifest,而不是内部依赖Jar的,推荐用这个代码片段来验证:
import java.io.IOException; import java.io.InputStream; import java.util.jar.Manifest; public class CheckManifest { public static void main(String[] args) { // 从当前类的类路径读取主Manifest try (InputStream is = CheckManifest.class.getResourceAsStream("/META-INF/MANIFEST.MF")) { if (is != null) { Manifest manifest = new Manifest(is); System.out.println("读取到的Manifest内容:"); manifest.getMainAttributes().forEach((key, value) -> System.out.println(key + ": " + value)); } else { System.err.println("未找到主Manifest文件"); } } catch (IOException e) { e.printStackTrace(); } } }
最后建议你先对比解压后的Manifest和Java代码读取的内容,看具体是哪些属性有差异,再针对性调整Ant脚本的配置,应该就能解决问题了。
内容的提问来源于stack exchange,提问作者QueenSpa
相关产品推荐
相关产品推荐

