You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:37:50