manifest.mf的一点理解
今天发现自己项目下存在commons-logging-1.1.jar和commons-logging.jar两个类包,就想看看commons-logging.jar包中的版本,
使用winwar打开类包,从META-INF文件夹下面MANIFEST.MF文件中查看相关信息,具体内容如下:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.5.3
Created-By: Blackdown-1.3.1_02b-FCS (Blackdown Java-Linux Team)
Extension-Name: org.apache.commons.logging
Specification-Vendor: Apache Software Foundation
Specification-Version: 1.0
Implementation-Vendor: Apache Software Foundation
Implementation-Version: 1.0.4
平日里只知道使用类包,还真没有仔细的看过该文件的信息,通过查看资料,自己写一下自己对这个文件的认识,仅仅是个人理解:
//用来定义manifest文件的版本。
Manifest-Version: 1.0
//个人理解:构建该类包使用的ANT版本。
Ant-Version: Apache Ant 1.5.3
//声明该文件的生成者,一般该属性是由jar命令行工具生成的,例如:Created-By: Apache Ant 1.5.1。(这是抄的别人的理解)
//个人理解:这里的“Blackdown Java-Linux Team”可能指的是一个团队。
Created-By: Blackdown-1.3.1_02b-FCS (Blackdown Java-Linux Team)
//该属性定义了jar文件的标识,自己还不是很理解“jar文件的标识”这个概念。
Extension-Name: org.apache.commons.logging
//个人理解:规范(接口)的制订人或者组织
Specification-Vendor: Apache Software Foundation
//个人理解:规范(接口)的版本。
Specification-Version: 1.0
//个人理解:该实现类的实现人或者组织
Implementation-Vendor: Apache Software Foundation
//个人理解:该实现类的具体版本,同样的规范版本不同的实现版本说明了实现类所能够实现的功能没有变
//(规范(接口)没有变化,但是实现细节发生了变化,可能会从性能等方面做了提升)。
Implementation-Version: 1.0.4
以下是参考文件:
参考文件:
http://hi.baidu.com/tlw_ray/blog/item/7b812ef454036a6cdcc47417.html
http://www-128.ibm.com/developerworks/cn/java/j-jar/
http://danmao.blogdriver.com/danmao/978761.html
下面转:http://hi.baidu.com/tlw_ray/blog/item/7b812ef454036a6cdcc47417.html
我平时用mf文件一般说来都是让jar成为可以直接运行这一目的。虽然目的这么简单,但是每次打包还是很容易出现各种各样的问题让人头痛。mf总是没有被应用,或者是出错了。
首先给出一个例子:
Manifest-Version: 1.0
Main-Class: ui.JFrameMain
Class-Path: jtds-1.2.jar c3p0-0.9.1.2.jar
esri_mo20.jar esri_mo20res.jar jsde83_sdk.jar
解释一下:
Manifest-Version mf文件版本号,这行照抄
Main-Class 包含main函数的类,程序的入口
Class-Path 用到的一些包
分析一下要点:
要点1:每行的“:”(冒号)用来分隔键值对。冒号后边一定要跟一个空格!!!
也就是说务必写为:
Main-Class:(空格)YouClassName
Class-Path:(空格)Class1.Jar
否则JBuilder会报("Manifest.mf": Error reading manifest: java.io.IOException: invalid header field
)这样的错。不再IDE帮助下做的JAR会发现MF没有起到应有的作用。顺便说一下以前我看到JBuilder报另一个个错大概说是什么换行符不对,好像也是由于这个问题引发的。原先总以为是windows里边的回车是由回车,换行2个字符构成而造成的。现在看来好像不是这样,是因为少了冒号后边那个空格。
要点2:Class-Path里边的内容用空格分隔而不是逗号或者分号。(唉。。。我总是下意识的用分号)
也就是说务必写成:
Class-Path:(空格)Class1.jar(空格)Class2.jar(空格)Class3.Jar
要点3:有的文章说MF文件每行不能超过七十多的字符,我的经验是如果在JBuilder里编辑MF超过了也无妨,一般我是尽量一行写完。续行挺麻烦又要以空格开头什么的。我也经常直接用winRar打开jar然后直接编辑里边的mf文件,这是个好方法,很直接了当,缺点就是如果改坏了也不会报错,只是MF有的部分失效了,好像运行时也会说"错误的MF文件版本"。
介绍几个技巧:
技巧1:使用winRar打开jar,双击MF文件,就可以编辑了,编辑完了Ctrl+S保存。特方便。也可以在外边写好一个Manifest.mf,然后直接拖入覆盖以前的。
技巧2:写一个run.bat来运行你的jar。run.bat大体内容如下:
java -jar yours.jar
pause
后边加一个pause就可以让你看到具体哪里出错了,一般来说问题如果出在MF上,那么往往就是哪个包,哪个类没有找到的NoClassDef这种异常
Java 产品打包成 JAR 文件,其中会在 META-INF 目录下边存在声明文件 MANIFEST.MF 。此文件内容为
KEY: VALUE ,这样的一行行内容。以下整理总结了各种标准规范中指定的 KEY 含义。
Manifest-Version
必有,但应该不用指定
Ant-Version
如果使用 Ant 的话,会由 Ant 自己加进来
Created-By: 1.6.0-b105 (Sun Microsystems Inc.)
如果使用 Ant 的话,会自动增加一个 Sun 的版本
Built-By
编译的人名,最好能是英文吧……
Extension-Name
Jar文件的标识。如果 Java 程序包符合规范的话,包(package)名应该符合这样的规则。
域名反序.项目名甲.模块名甲.xxx
比如一个完整类全名:cn.spads.soccerms.data.dao.RamMatchDao
如果是一个模块封装成 .jar 的话,会存在其它任何 .jar 包都绝不可能出现这样的包:
cn.spads.soccerms.data.*
于是,可以认为 cn.spads.soccerms.data 是当下这个 .jar 包所独有的 Java 类包名前缀。
于是用词作为 .jar 文件的唯一标识,非常合适。
Name
签名用的“姓名”,推荐将产品名称放在这里,或者是产品模块的名称。
Comment
注释,对产品的说明
Specification 和 Implementation
Specification 是标准。比如 Servlet 标准,可能还有 JDBC 标准。
Implementation 是针对这个标准的产品。
如果没有特别的名字,其中 -Title 可以用和 Name 一致的内容,比如 Spads Soccer Management
具体来说,有通用的 Title, Version 和 Vendor ;
还有 Implementation-Vendor-Id 和 Implementation-URL
Sealed
只有 true 和 false 二种值。
其中 true 意味着此 .jar 包拒绝别的 .jar 包里边的程序直接加载当前 .jar 包里边的类。
对于组件型 .jar 包,应该是 false ;对于封装的 Java 应用,可以考虑用 true 。
Class-Path
每个类路径用空格分隔,同时换行的话要以空格作为行首第一个字符。
此类路径的基准是当前 .jar 文件所在目录。类路径应该是以此为基准的相对路径。
比如存在文件结构:
SoccerMS [目录]
soccer-ms-1.1.0.jar
lib [目录]
mysql-connector-java-5.1.18-bin.jar
postgresql-9.1-901.jdbc4.jar
那么 soccer-ms-1.1.0.jar 中 MANIFEST.MF
Main-Class
一定要写类全名。此类中应包含 static public void main(String[] xxx) 方法,即主方法。
然后可以通过命令行的 java -jar xxxx.jar 来运行 .jar 文件。
实际操作中,一个 .jar 包很可能实现了很多规范。于是 MANIFEST.MF 会有如下集中的段落:
- ############ 第 1 份规范 ###########
- Specification-Title: Java API for XML Processing
- Specification-Vendor: Sun Microsystems Inc.
- Specification-Version: 1.3
- Name: org/apache/xalan/
- Comment: Main Xalan engine implementing TrAX/JAXP
- Implementation-Title: org.apache.xalan
- Implementation-Version: @impl.version@
- Implementation-Vendor: Apache Software Foundation
- Implementation-URL: http://xml.apache.org/xalan-j/
- Name: org/apache/xpath/
- Comment: XPath engine
- Implementation-Title: org.apache.xpath
- Implementation-Version: @impl.version@
- Implementation-Vendor: Apache Software Foundation
- Implementation-URL: http://xml.apache.org/xalan-j/
- ############ 第 2 份规范 ###########
- Specification-Title: Runtime component of JCup
- Specification-Vendor: Princeton University
- Specification-Version: 0.10k
- Name: java_cup/runtime/
- Comment: Runtime component of JCup
- Implementation-Title: runtime
- Implementation-Version: @impl.version@
- Implementation-Vendor: Princeton University
- Implementation-URL: http://www.cs.princeton.edu/~appel/modern/java/CUP/
对于多段规范被实现,每个规范被多个部分联合实现,可以参看下边的例子,是一个很完整的例子。
http://www.oschina.net/code/explore/xalan/xalan-j_2_7_1/src/MANIFEST.MF
另外可以去看看以下这篇帖子,其中讲到了手动编写 MANIFEST.MF 文件的一些心得。
http://hi.baidu.com/lkdlhw_2000/blog/item/195519663df40920aa184ceb.html
这篇帖子在网上广泛流传,为防止地址打不开,给几个格式比较好的转载:
http://happysky.iteye.com/blog/391610
http://blog.163.com/shucker_gzb/blog/static/64514485200951815712456/