在java中jar文件是一个zip格式的压缩文件,虽然属于zip格式的压缩文件,但是java规范里面对于jar文件还有不少额外的设定,作为一名java开发者,我们应该了解一下。
1、基本概念
我们可以对一个jar文件进行签名,而有的工具或者容器则可以认识或解析我们所设置的签名,从而给这个jar程序赋予相应的权限或者发现代码是否曾被修改过。
Package Sealing: 来自同一个package的class文件都必须来自同一个jar文件。这样做的目的是为了保持版本一致性和安全。
Package Versioning: jar文件可以包含关于Vendor和Version的信息。
2、META-INF目录
这个目录存放的都是一些meta数据。可括如下文件:
MANIFEST.MF:最常用的一个文件,定义扩展属性,如版本,类包依赖等。
INDEX.LIST:用jar命令-i参数可以生成该文件,用于让ClassLoader可以加快装载class到jvm,估计适合Applet这种需要下载和装载远程的class的场景。
xxx.SF: 是本jar文件的签名。
xxx.DSA: 跟签名相关。
3、jar文件可以设置为“可执行”文件。
jar文件“可执行”的意义在于:
(1)在windows里双击该文件可以运行启动应用;
设置方法是设置jar文件中的META-INF目录中的MANIFEST.MF文件。
加入一行:Main-Class: com.mypackage.MyMainClass 即可
也可以采用Ant来设置或者生成这句话。
<jar destfile="myapp.jar" basedir="classes">
<manifest>
<attribute name="Main-Class" value="com.mypackage.MyMainClass" />
</manifest>
</jar>
(2)用命令行或者cmd,sh等脚本可以运行启动jar文件。
用命令行启动的方式是:java -jar myapplication.jar
4、Package Sealing
可以在MANIFEST.MF文件中设定类似如下的内容:
Name: com/mypackage/
Sealed: true
那么,你的package(com.mypackage)的类就必须都来自这同一个jar文件,否则JVM就会抛出异常。
5、jar文件中可以设定对其他jar的依赖关系
如果jar的运行需要引用其他jar,那么可以在 MANIFEST.MF中设定或者列出其他的jar。
列举时需要列出具体位置和文件名,如果用相对路径,则始于此jar所在的目录起,如果用绝对路径,则在Unix/Linux路径下用/开头,在Windows中似乎得用file:///。然后再接着Windows的路径,如:
Class-Path: ./lib/log4j-1.2.11.jar
../otherlib/otherfile.jar
/share/lib/somefile.jar
//上面是Unix/Linux绝对路径
file:///D:/mydemo/myapp/lib/log4j-1.2.11.jar
//上面是Windows绝对路径
如果有多个依赖,则用空格或者回车隔开都可以。
同样可以用Ant来设置。
<attribute name="Class-Path" value="./lib/a.jar ./lib/b.jar" />
6、可以把其他类型的文件(非.class文件)放到jar文件中
常规的如.properties文件,.xml文件都是经常放配置信息的,这些文件都可以放到.jar文件中。其实可以放一些图片,音频等,并且同样可以在应用程序中读取到这些文件。当然,不要放太大的文件,以免影响性能。
读取这些文件的方法很简单,就是类似MyClass.class.getClassLoader().getResourceAsStream(“/myfiles/myfile.xml”)的写法即可拿到一个InputStream。
7、Package Versioning
可以在jar中放入版本信息,如:
Name: java/util/
Specification-Title: “Java Utility Classes”
Specification-Version: “1.2”
Specification-Vendor: “Sun Microsystems, Inc.”.
Implementation-Title: “java.util”
Implementation-Version: “build57”
Implementation-Vendor: “Sun Microsystems, Inc.”
8、 引入jar的另外方法
a、把jar文件放到JRE的lib/ext目录下,将隐性地能够被你的应用所引用到,即不需要显式出现在CLASSPATH或者你的MANIFEST.MF中;
b、Java6开始允许使用通配符来设定CLASSPATH,如java -classpath .\lib* myapp.jar,这样的话,lib地下的n个jar文件自动加入到CLASSPATH中,而不需要一一列举了。可惜不能在MANIFEST.MF中使用通配符。
另外,在J2EE环境下,我们通常部署ear/war,这些部署文件中都有大量的应用代码(.class文件),J2EE没有限制和规定这些.class文件是否一定要打包成.jar文件,如war目录中,可以采用在WEB-INF/classes里面放置大量的.class文件,虽然逻辑上是一样的东西,但是运行态是不同的。如果不打包的话,系统进程(Java服务器,如WebLogic)会需要用多个IO操作来打开程序文件,使用多个文件句柄;如果是打包成.jar的话,则其相关的数量可以大大降低。各自优劣,不言自明。