打包文件 MANIFEST.MF 功能详解
最近研究了如何在java工程打包,期间遇到的一些问题进行总结,如打包成test.jar 文件
Manifest-Version: 1.0 Main-Class: windows.VideoWindow Class-Path: lib\jetty-6.1.26.jar lib\aspectjweaver-1.6.12.jar
上面为打包为jar中的包说明文件. 下面这个报错一直出现. could not find main class. Program will exit 这个错误提示其实不是没有发现main class. 而是jar如果有错误执行不了,就会出现这个错误. 打包完成后, 要先运行 cmd -> java -jar your.jar 确认没有问题即可执行jar. 使用-jar参数后, 系统的Classpath 变量不再起作用. 虚拟机将去MANIFEST.MF中的Class-Path 下找相关的包. 然后才能成功的从: windows.VideoWindow 的main方法进入. 否则没有相关连接包,则会提示找不到main class. 而大家可能还迷糊的找不到北. 明明有main class吗.
如果这个写的不对. 则就会一直报错. 看看上面这个Class-Path: 后面的写法. 空格分开. 绝对不能有分号.切记.
最后必须有换行. 这个也是要注意的. 否则依然提示没有mainclass.
不要因为这个小事情耽误了时间. 其中 lib/ 表示这个jar必须在打包Test.jar所在目录的一个lib子目录中.
运行jar需要命令: java -jar Test.jar 双击也可以, 则使用 javaw 打开.
关于java -classpath a.jar;b.jar; class test.Test 执行时. a.jar;b.jar; 后面都必须有分号. 否则报错. 不要指望不写classpath让系统自己找. 这不是在eclipse里面.必须写上你要使用的类. 否则总会提示您编译出错.
2、MANIFEST.MF 文件中奇怪的分行和空格要求
工作中发现的一个非常奇怪也很有趣事情,有关MANIFEST.MF文件中的分行和空格的格式要求,分享给大家。
对于通常的MANIFEST.MF文件,一般格式是:
Class-Path: lib/a.jar lib/b.jar lib/c.jar lib/d.jar lib/e.jar lib/f.jar 在一行之内将所有的jar包路径写上,空格分隔即可。
但是对于一些大型的项目,因为依赖包众多,比如大于30个,那么如果还写在一行内,就会出现一个长度惊人的行。程序运行倒不会有任何问题,但是对于版本控制就很不友好,如增加或者减少一个依赖包,这行就会被改写。以后compare不同版本时,只能知道这行被修改了确无法直接知道是做了什么修改,必须通过其他方式才能对比出来。
同样的问题发生在code merge时,如果两个分支都修改了这个文件,就必须通过手工来进行merge,而且要对照出来彼此到底改了什么,很困难而且容易出错。
因此一个改进就是将这个文件中的依赖按照一行一个依赖的方式重写,这样以后修改时只会修改改依赖所在的行,很容易就对比出来具体做了哪些感动,code merge时版本控制软件一般也很容易直接自动merge成功。
修改后的文件类似如下:
Class-Path: lib/a.jar lib/b.jar lib/c.jar lib/d.jar lib/e.jar lib/f.jar
但是在实际操作时发生了意料之外的问题,会出现异常或者类无法找到,经检查发现问题出现在MANIFEST.MF的格式上,MANIFEST.MF对于分行和空格是有特殊要求的:
1. 每行的最后一个jar的名称后不容许有空格 即" lib/b.jar"在b.jar后必须回车结束本行,不能有空格,一个都不能
2. 每行的开头必须有不少于2个空格 即" lib/b.jar"在b.jar前必须有不下两个空格
以上两个条件有一个不满足都会出现问题,有点古怪。
3、严格的MANIFEST.MF格式 今天才发现这个文件的格式要求比较严格,因为使用的包比较多,所以那个Class-path的内容就比较多,我全部放在了一行,结果服务器启动读取那个文件的时候报错,错误信息是行太长,把它们切成多行,结果又是无效的头字段(java.io.IOException: invalid header field),和工程里面的其它文件比较了下,发现换行后要在前面加一个空格,后来又发现明明包含了一个包,但是找不到类,又在每行的后面加了一个空格,这下才完全搞定。