本文参考了:
http://docs.oracle.com/javase/tutorial/deployment/jar/basicsindex.html
The Java™ Archive (JAR) file format enables you to bundle multiple files into a single archive file. Typically a JAR file contains the class files and auxiliary resources associated with applets and applications.
jar使用的是zip压缩技术,我们也可以选择不压缩。
- 基本命令
基本的打jar包的命令很简单:
jar cf test.jar input-file(s)
cf的意思是打一个jar文件。其他参数请自己查询。
test.jar是指定的jar文件的名字。
input-file(s)是指定哪些文件应该被包括到jar中去。通常是代码编译后产生的class文件。另外如果代码中引用了其他类库,也就是jar包。我们可以一并和源代码打到一个jar包里,这样运行时,一个jar包就够了。如果选择仅将源代码打进jar包,则在程序运行时,还必须将需要的类库放到合适的地方并加入classpath中。
- manifest 文件
执行完上面的命令后,就生成了一个jar包。如果我们解压这个jar包,可以看到这样一个文件:
META-INF/MANIFEST.MF,内容是:
Manifest-Version: 1.0
Created-By: 1.7.0 (Oracle Corporation)
这是自动生成的manifest文件。
此时如果运行:
java -jar test.jar
将会返回:
Failed to load Main-Class manifest attribute from test.jar
程序无法运行,因为java不知道程序的入口在哪。
- Main-Class header in manifest file
通过在manifest file中指定Main-Class属性,就可以告诉程序入口了。有两种方法:
1,手工修改mafifest file。
We first create a text file named Manifest.txt
with the following contents:
然后运行:
jar cfm MyJar.jar Manifest.txt MyPackage/*.class
m的意思是使用一个已有的manifest文件。此时java -jar MyJar.jar就可以工作了。
2,使用参数e
jar cfe app.jar MyApp MyApp.class
参数e将manifest文件中的Main-class设置为:MyApp 。这样就不用手工修改文件了。
另外说一下引用第三方类库的问题。前面说了,可以将java代码依赖的第三方类库一并打包进一个jar文件,也可以只将java代码放进jar文件,在程序运行时再另外指定classpath。
对于第二种方式,manifest文件中,还有一个属性,class-path。使用这个属性,我们就可以直接指定classpath了,而不是在每次运行的时候麻烦的单独指定。
注意,这种方式有以下限制:
The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file calledMyUtils.jar, you cannot use theClass-Path header inMyJar.jar's manifest to load classes inMyUtils.jar into the class path.
例如,MyApp.jar在运行时需要一个MyUils.jar。首先造一个manifest文件,加入以下内容:
class-path: directory-name/MyUils.jar
和前面一样,运行jar cfm,使用已有的manifest文件生成jar文件,该jar文件仅包含MyApp的class文件:
jar cfm MyJar.jar Manifest.txt MyPackage/*.class
然后MyApp.jar就可以直接运行,而不必指定classpath了:
java -jar MyApp.jar
我们还可以在manifest文件中指定package的版本:
http://docs.oracle.com/javase/tutorial/deployment/jar/packageman.html
对于第一种方式,即在运行时指定classpath:
java -cp ${CLASSPATH} main-class
需要注意的是 ${CLASSPATH} 不能使用类似/folder/* 这样来指定将一个目录下的所有jar包都加到class-path中,注意下面的话:
For a .jar or .zip file that contains .class files, the class path ends with the name of the .zip or .jar file
因此只能是这样的:
CLASSPATH="$codeHome/lib/commons-collections-3.2.1.jar:$codeHome/lib/commons-io-2.0.jar:$codeHome/lib/saxon-xpath-8.7.jar"
CLASSPATH=.;D:\JAVA\LIB;C:\DOC\JavaT
最后,由于现在maven在广泛使用,因此很少直接用jar命令去打包了。关于如何用maven打包,请参看我的另外一篇文章Maven的使用经验(二)--打包