4.8 JAR文件

4.8 JAR文件

将应用程序打包时,你一定希望只向用户提供一个单独的文件,而不是一个包含大量类文件的目录结构,java归档(JAR)文件就是为此目的而设计的。一个JAR文件既可以包含类文件,也可以包含诸如图像和声音等其他类型的文件。此外,JAR文件是压缩的,它使用了我们熟悉的ZIP压缩格式。

4.8.1 创建JAR文件

可以使用jar工具制作JAR文件,在默认的JDK安装中,这个工具位于jdk/bin目录下。
创建一个新的JAR文件最常用的命令使用以下语法:
jar cvf jarFileName file1 file2 …
例如:
jar cvf CalculatorClasses.jar *.class icon.gif
通常,jar命令的格式如下:
jar options file1 file2 …
表4-2列出了jar程序的所有选项。类似于UNIX tar命令的选项。
可以将应用程序和代码库打包在JAR文件中。例如,如果想在一个java程序中发送邮件,就可以使用打包在文件javax.mail.jar中的一个库。
c 创建一个新的或者空的存档文件并加入文件。如果指定的文件名是目录,jar程序将会对它们进行递归处理
C 临时改变目录,例如: jar cvf jarFileName.jar -C classes 星号.class 切换到classes子目录以便增加类文件。
e 在清单文件中创建一个入口点(参考4.8.3)
f 指定JAR文件名作为作为第二个命令行参数。如果没有这个参数,jar命令会将结果写至标准输出(在创建JAR文件时)或者从标准输入读取(在解压或者列出JAR文件内容时)
i 建立索引文件(用于加快大型归档中的查找)
m 将一个清单文件添加到JAR文件中。清单是对归档内容和来源的一个说明。每个归档有一个默认的清单文件。但是,如果想验证归档文件的内容,可以自己提供清单文件。
M 不为条目创建清单文件
t 显示内容表
u 更新一个已有的 JAR文件
v 生成详细的输出结果
x 解压文件。如果提供一个或多个文件名,只解压这些文件;否则,解压所有文件
0(零) 存储,但不进行ZIP压缩

4.8.2 清单文件

除了类文件、图像和其他资源外,每个JAR文件还包含一个清单文件,用于描述归档文件的特殊特性。
清单文件被命名为MANIFEST.MF,它位于JAR文件的一个特殊的META-INF子目录中。符合标准的最小清单文件极其简单:
Manifest-Version: 1.0
复杂的清单文件可能包含更多条目。这些清单条目被分成多个节。第一节称为主节。它作用于整个JAR文件。随后的条目用来指定命名实体的属性,如单个文件、包、或者URL。它们都必须以一个Name条目开始。节与节之间用空行分开。例如:
Manifest-Version:1.0
lines describing this archive

Name:Woozle.class
lines describing this file
Name:com/mycompany/mypkg/
lines describing this package

要想编辑清单文件,需要将希望添加到清单文件的行放到文本文件中,然后运行:
jar cfm jarFileName manifestFileName …
例如,要创建一个包含清单文件的JAR 文件,应该运行:
jar cfm MyArchive.jar manifest.mf com/mycompany/mypkg/*.class
要想更新一个已有的JAR文件的清单,则需要将增加的部分放置到一个文本文件中,然后执行以下命令:
jar ufm MyArchive.jar manifest-additions.mf

4.8.3 可执行JAR文件

可以使用jar命令中的e选项指定程序的入口点,即通常需要在调用java程序启动器时指定的类。:
jar cvfe MyProgram.jar com.mycompany.mypkg.MainAppClass files to add
或者,可以在清单文件中指定程序的主类,包括以下形式的语句:
Main-Class: com.mycompany.mypkg.MainAppClass
不要为主类名增加扩展名 .class。
警告:清单文件的最后一行必须以换行符结束。否则,清单文件将无法被正确地读取。常见的一个错误是创建了一个只包含Main-Class行而没有行结束符的文本文件。
不论使用哪一种方法,用户可以简单地通过下面的命令来启动程序:
java -jar MyProgram.jar
取决于操作系统的配置,用户甚至可以通过双击JAR文件图标来启动应用程序。下面是各种操作系统的操作方式:

  • 在windows平台中,java运行时安装程序将为“.jar”扩展名创建一个文件关联,会用javaw -jar 命令启动文件。与java命令不同,javaw命令打不开shell窗口
  • 在Mac OS X 平台中,操作系统能够识别“.jar”扩展名文件。双击JAR文件时就会执行java程序
    不过,人们对JAR文件中的java程序与原生应用还是感觉不同。在windows平台中,可以使用第三方的包装器工具将JAR文件转换成windows可执行文件。包装器是一个windows程序,有大家熟悉的扩展名.exe,它可以查找和加载虚拟机,或者子啊没有找到JVM时会告诉用户应该做些什么。

4.8.4 多版本JAR文件

随着模块和包强封装的引入,之前可以访问的一些内部API不再可用。例如,JavaFX 8 有一个内部类com.sun.javafx.css.CssParser。如果用它解析一个样式表,你会发现你的程序不再能正常编译了。补救很简单,只需要改用Java9提供的javax.css.CssParser。不过这样会有一个问题。你需要向Java 8 和 Java 9用户发布不同的应用程序。或者需要利用类加载和反射等一些技巧。
为了解决类似这样的问题,Java 9引入了多版本JAR,其中可以包含面向不同Java版本的类文件。
为了保证向后兼容,额外的类文件放在META-INF/versions目录中。
假设Application类使用了CssParser类。那么遗留版本的Application.class文件可以使用com.sun.javax.css.CssParser,而java 9 版本可以使用javafx.css.CssParser。
Java 8 完全不知道META-INF/versions目录,它只会加载遗留的类。java 9 读取这个JAR文件时,则会使用新版本。
要增加不同版本的类文件,可以使用 --release 标志:
jar uf MyProgram.jar --release 9 Application.class
要从头构建一个多版本JAR文件,可以使用 -C 选项,对应每个版本要切换到一个不同的类文件目录:
jar cf MyProgram.jar -C bin/8 . --release 9 -C bin/9 Application.class
面向不同版本编译时,要使用–release 标志和-d 标志来指定输出目录:
javac -d bin/8 --release 8 …
在java 9中, -d 选项会创建这个目录(如果原先该目录不存在)。
–release 标志也是java 9新增的。在较早的版本中,需要使用-source 、-target和-bootclasspath 标志。JDK现在为之前的两个API版本提供了符号文件。在java 9中,编译时可以将–release 设置为9 、8 或7.
多版本JAR并不适用于不同版本的程序或库。对于不同版本,所有类的公共API都应当是一样的。多版本JAR的唯一目的是支持你的某个特定版本的程序或库能够在多个不同的JDK版本上运行。如果你增加了功能或者改变了一个API,那就应当提供一个新版本的JAR。
注释:javap 之类的工具并没有改造为可以处理多版本JAR文件。如果调用:
javap -classpath MyProgram.jar Application.class
你会得到类的基本模板,毕竟,它与更新的版本因该有相同的公共API。如果必须查看更新的版本,可以调用:
javap -classpath MyProgram.jar!/META-INF/versions/9/Application.class

4.8.5 关于命令行选项的说明

java开发包(JDK)的命令行选项一直以来都是使用单个短横线加多字母选项名的形式,如:
java -jar …
javac -Xlint:unchecked -classpath …
但jar命令是个例外,这个命令遵循经典的tar命令选项格式,而没有短横线:
jar cvf …
从Java 9开始,java工具开始转向一种更常用的选项格式,多字母选项名前面加两个短横线,另外对于常用的选项可以使用单字母快捷方式。例如,调用linux ls 命令时可以提供一个 “human-readable”选项:
ls --human-readable
或者
ls -h
在java 9中,可以使用–version而不是-version,另外可以使用 --class-path而不是-classpath。在本书的卷二第九章可以看到,–module-path选项有一个快捷方式-p。
详细的内容参见JEP293增强请求。在所有清理工作中,作者还提出要标准化选项参数。带–和多字母的选项的参数用空格或者一个等号分隔:
javac --class-path /home/user/classdir…

javac --class-path=/home/user/classdir…
单字母选项的参数可以用空格分隔,或者直接跟在选项后面:
java -p moduledir…

java -pmoduledir…
警告:后一种方式现在不能使用,而且一般来讲这也不是一个好主意。如果模块目录恰好是arameters或rocessor,这就很容易与遗留的选项发生冲突,这又何必呢
无参数的单字母选项可以组合在一起:
jar -cvf MyProgram.jar -e mypackage.MyProgram 星号/星号.class
警告:目前不能使用这种方式。这肯定会带来混淆。假设javac有一个-c选项。那么javac -cp是指javac -c -p 还是-cp?
这就会带来一定混乱,希望过段时间能够解决这个问题。尽管我们想要远离这些古老的jar选项,但最好还是等到尘埃落定为妙。不过,如果你想做到最现代化,那么可以安全的使用jar命令的长选项:
jar --create --verbose --file jarFileName file1 file2 …
对于单字母选项,如果不组合,也是可以使用的:
jar -c -v -f jarFileName file1 file2 …

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值