jar包的解压缩和压缩后重新运行,报错:xxx.jar中没有主清单属性

同学们可以私信我加入学习群!

在这里插入图片描述


前言

我使用插件yauzl把jar包解压缩、修改properties、压缩后,发现新的jar包无法运行,提示:xxx.jar中没有主清单属性

然后通过对比新jar包和旧jar包发现,两者不论从文件内容还是文件层级,都是一模一样的,除了最终jar包大小不同。

所以合理猜测,因为压缩方式的不同,导致不同压缩比例的jar包会无法运行。


一、手动模拟过程定位问题

现在最重要的是定位问题。我大概经历了以下几步:

  1. 排除properties改变带来的影响:

我将未修改的properties放到新jar包中,发现新jar包还是无法运行,然后新jar包修改过的properties放到旧jar包中,发现旧jar包可以运行,可以得出结论,新jar包无法运行,和修改properties无关。

  1. 我的代码主要功能是以下三步自动化:

a)jar包解压缩。
b)修改properties
c) 修改后的文件夹压缩回jar包

用解压缩软件,手动的方式重复上面a c两个步骤,其b步骤可能的影响已经排除。发现jar经过手动解压缩和压缩后,新的jar就不能运行。

由此可知,影响jar包运行的可能不是我们的代码,而是和压缩方式有关。

  1. 通过观察,发现新旧jar包虽然所有文件内容、文件层级都相同,但是最终的jar包大小有差别,所以尝试用存储方式(不做任何压缩)压缩文件,得到jar包,然后运行正常。

现在就可以定为到问题:jar包经过代码解压缩、配置文件修改、压缩后,无法正常运行的原因可能和jar包压缩方式有关。

二、jdk提供的jar包压缩工具

jdk提供了jar包的文件处理、jar包解压缩、jar包压缩工具,这也是为什么我要把jre改成jdk的原因,但是这样有两个不好的地方:一是环境变大;二是jar包和jdk强关联绑定。不过目前还是采用这个最简单的方案。

jdk提供的jar包工具提供了参数0(这是阿拉伯数字零),在产生jar包时不对其中的内容进行压缩处理。

我原来的命令:

${jdkPath}\\bin\\jar vcf0 ${jarPath} -C ${copyPath} . 

代码含义是找到jdk路径,在jdk路径下运行jar命令,命令参数是vcf0,jar包地址是jarPath,要压缩的文件目录是copyPath。


2023年8月15日更新:
如果jar包过于复杂时,全包压缩和解压总是容易出问题,会修改其中的某些文件。所以最终采用更新文件的方式:

${jdkPath}\\bin\\jar uvf ${jarPath} -C ${copyPath}  BOOT-INF\\classes\\midstation.properties 

主要由两处更改:

  1. 参数改为uvf
  2. copyPath后面跟着的不再是’.',而是指定相对路径“BOOT-INF\classes\midstation.properties”

总结

目前项目中关于文件解压缩的工具有两三个(jar包也是一种压缩包),有点冗余,后期在把前端部署的工具也完成后,应该寻找一个最佳实践方案,尽量统一。

大胆怀疑,细心求证。少说话,多做事,不做无谓的精神内耗。
——中二少年。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当您使用Maven的`maven-jar-plugin`打包项目并尝试运行生成的`.jar`文件时,如果报错说".jar没有清单属性",这通常表示Maven没有在生成的JAR包含Maven的元数据,也就是`META-INF/MANIFEST.MF`文件,该文件包含了关于应用程序的基本信息,如类(Main-Class)等。 解决这个问题的步骤可能包括: 1. **检查pom.xml配置**:确保在`<build>`标签下`<plugins>`部分的`maven-jar-plugin`配置,`<archive>`元素包含了`<manifest>`子元素。例如: ```xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <classpathPrefix>lib/</classpathPrefix> <mainClass>com.example.MainClass</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> ``` 这里`<mainClass>`是你程序的全限定名。 2. **添加MANIFEST.MF手动**:如果在`pom.xml`找不到或配置不正确,你可以手动创建一个`MANIFEST.MF`文件,并放入项目的根目录下,内容应类似上面`<manifest>`标签的内容。 3. **检查是否包含类**:确保你的类是在打包时会被包含的。如果你有一个Java入口类(如`public class Main`),记得在`<mainClass>`指定它。 4. **清理和重新构建**:删除目标目录(通常是`target`)下的所有文件,然后运行`mvn clean install`重新构建,以确保所有的设置都被正确处理。 相关问题: 1. 清单属性是什么,为什么打包时需要它? 2. Maven如何自动添加MANIFEST.MF文件? 3. 如果我已经指定了类,为什么还会报这个错误?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

中二少年学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值