有时我们会遇到这种情况:一堆jar文件看着麻烦,要做成一个可执行jar文件(java -jar myjar.jar xxx方式执行的jar)时,希望把所有依赖的jar包打包到可执行jar文件中,可是如何将jar文件中的jar自动加到classpath中呢?
第一反应,最直接的方法有两个:
1. 将外层的jar文件解压到一个临时目录中,通过URLClassloader加载解压出的jar文件中的类。
这种方法需要一个外部临时目录,占用了外部空间,有了外部依赖,并且解压需要耗费一定时间,对于需要快速执行的程序并不适合。因此这种方法虽然一定可行,但有很多局限性。
2. 通过Class.getResource()方法获得内部jar文件的URL,然后使用URLClassloader将这些内部jar文件中的类加载。
这种方法看起来不错,既不占用外部空间,又不需要解压,但实施起来有问题,URLClassloader无法处理“jar中jar”类型的URL!
既然这两种方法都不行(不好),只能找其他的方法了。最麻烦的方法是自己写Classloader,将jar中的jar读出来,从里面加载需要的类,这种方法可行,但需要自己写classloader,比较繁琐,有没有人已经写好了这个classloader呢?google “jar in jar”,在网上找到了One-Jar和eclipse自带的“jar in jar loader”,这两个软件都实现了加载jar中jar的classloader。从功能上来说,One-Jar功能更强一些,它允许将外层jar中的某些文件解压到文件系统中,这样当运行时需要有些文件放到文件系统中时比较方便。One-Jar是Simon tuffs老头写的,用的比较多。
另外,网上还有一个FatJar的sourceforge工程,这是一个eclipse插件,提供export wisard,可以把一个工程和相关的jar包一起export出去,直接将相关jar包展开到打出的jar包中,另外,也可以集成one-jar,此时相关的jar包不会被展开。
从eclipse3.4开始,JDT中添加了一个简化的FatJar版本,提供Runnable Jar File导出向导,导出时使用eclipse自带的“jar in jar loader”,没有用One-Jar的classloader。但个人感觉目前JDT自带的Runnable Jar File导出向导已经比FatJar好用了,不但可以将相关的jar包在打出的jar包中展开,也可以不展开,还可以把依赖jar包打到外层jar包的外面,另外,还可以直接和LaunchConfiguration集成。