zoukankan      html  css  js  c++  java
  • MANIFEST.MF的详解及用途

    打开Java的JAR文件我们经常可以看到文件中包含着一个META-INF目录,这个目录下会有一些文件,其中必有一个MANIFEST.MF,这个文件描述了该Jar文件的很多信息,下面将详细介绍MANIFEST.MF文件的内容,先来看struts.jar中包含的MANIFEST.MF文件内容: 

    Manifest-Version: 1.0
    Created-By: Apache Ant 1.5.1
    Extension-Name: Struts Framework
    Specification-Title: Struts Framework
    Specification-Vendor: Apache Software Foundation
    Specification-Version: 1.1
    Implementation-Title: Struts Framework
    Implementation-Vendor: Apache Software Foundation
    Implementation-Vendor-Id: org.apache
    Implementation-Version: 1.1
    Class-Path:  commons-beanutils.jar commons-collections.jar commons-digester.jar commons-logging.jar commons-validator.jar jakarta-oro.jar struts-legacy.jar

    如果我们把MANIFEST中的配置信息进行分类,可以归纳出下面几个大类:

    一. 一般属性

    1. Manifest-Version
     用来定义manifest文件的版本,例如:Manifest-Version: 1.0

    2. Created-By
     声明该文件的生成者,一般该属性是由jar命令行工具生成的,例如:Created-By: Apache Ant 1.5.1

    3. Signature-Version
     定义jar文件的签名版本

    4. Class-Path
     应用程序或者类装载器使用该值来构建内部的类搜索路径

    二. 应用程序相关属性

    1. Main-Class
     定义jar文件的入口类,该类必须是一个可执行的类,一旦定义了该属性即可通过 java -jar x.jar来运行该jar文件。
     
    三. 小程序(Applet)相关属性

    1. Extendsion-List
     该属性指定了小程序需要的扩展信息列表,列表中的每个名字对应以下的属性
    2. <extension>-Extension-Name
    3. <extension>-Specification-Version
    4. <extension>-Implementation-Version
    5. <extension>-Implementation-Vendor-Id
    5. <extension>-Implementation-URL

    四. 扩展标识属性

    1. Extension-Name
     该属性定义了jar文件的标识,例如Extension-Name: Struts Framework
     
    五. 包扩展属性
     
    1. Implementation-Title   定义了扩展实现的标题
    2. Implementation-Version   定义扩展实现的版本
    3. Implementation-Vendor   定义扩展实现的组织  
    4. Implementation-Vendor-Id   定义扩展实现的组织的标识
    5. Implementation-URL :   定义该扩展包的下载地址(URL)
    6. Specification-Title   定义扩展规范的标题
    7. Specification-Version   定义扩展规范的版本
    8. Specification-Vendor   声明了维护该规范的组织
    9. Sealed   定义jar文件是否封存,值可以是true或者false (这点我还不是很理解)

    六. 签名相关属性

    签名方面的属性我们可以来参照JavaMail所提供的mail.jar中的一段

    Name: javax/mail/Address.class
    Digest-Algorithms: SHA MD5 
    SHA-Digest: AjR7RqnN//cdYGouxbd06mSVfI4=
    MD5-Digest: ZnTIQ2aQAtSNIOWXI1pQpw==

    这段内容定义类签名的类名、计算摘要的算法名以及对应的摘要内容(使用BASE64方法进行编码)

    七.自定义属性

    除了前面提到的一些属性外,你也可以在MANIFEST.MF中增加自己的属性以及响应的值,例如J2ME程序jar包中就可能包含着如下信息

    MicroEdition-Configuration: CLDC-1.0
    MIDlet-Name: J2ME_MOBBER Midlet Suite
    MIDlet-Info-URL: 
    http://www.javayou.com/
    MIDlet-Icon: /icon.png
    MIDlet-Vendor: Midlet Suite Vendor
    MIDlet-1: mobber,/icon.png,mobber
    MIDlet-Version: 1.0.0
    MicroEdition-Profile: MIDP-1.0
    MIDlet-Description: Communicator

    关键在于我们怎么来读取这些信息呢?其实很简单,JDK给我们提供了用于处理这些信息的API,详细的信息请见java.util.jar包中,我们可以通过给JarFile传递一个jar文件的路径,然后调用JarFile的getManifest方法来获取Manifest信息。

     

    用途主要有二:

        1. Main-Class 指定程序的入口,这样可以直接用java -jar xxx.jar来运行程序。

        2. Class-Path 指定jar包的依赖关系,class loader会依据这个路径来搜索class。

    我平时用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

    例子: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:有的文章说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这种异常。

  • 相关阅读:
    leetcode教程系列——Binary Tree
    《Ranked List Loss for Deep Metric Learning》CVPR 2019
    《Domain Agnostic Learning with Disentangled Representations》ICML 2019
    Pytorch从0开始实现YOLO V3指南 part5——设计输入和输出的流程
    Pytorch从0开始实现YOLO V3指南 part4——置信度阈值和非极大值抑制
    Pytorch从0开始实现YOLO V3指南 part3——实现网络前向传播
    Pytorch从0开始实现YOLO V3指南 part2——搭建网络结构层
    Pytorch从0开始实现YOLO V3指南 part1——理解YOLO的工作
    让我佩服的人生 文章
    win8.1配置cordova+ionic等一系列东西
  • 原文地址:https://www.cnblogs.com/blogyuan/p/2796674.html
Copyright © 2011-2022 走看看