(这篇文章真的很不错)
又是一个无聊的周末,硬着头皮给客户想出一套java程序打包的解决方案
目标:有安装程序包像安装qq一样简单一直下一步即可 ,可卸载,要求程序自动启动,不需要单独安装JRE,就在写这套解决方案的时候,我真是百般痛恨微软.哎无奈啊.幸好最终还是被我想出来了,分享下吧,好久不写博了.
第一步 jre减肥,删除jre/lib/rt.jar中不使用的类,删除charsets.jar中不使用的字符集编码.MyWork开源项目(http://mywork.sourceforge.net/)中带了一个瘦身过的JRE6.0,非常小只有几M.如果有需要可在此基础上适当的增肥,例如提示有类找不到,只要在完整的jre下rt.jar包中找到这个类所在的包添加到瘦身过的jre即可.
第二步使用pack200进行压缩,压缩效果非常惊人,具体用法可参考官方手册,下面是最简单的压缩和解压缩命令(如果要制作安装包的话不建议压缩,因为不方便解压缩,还需要另外写程序进行解压)
压缩命令D:/xxxxx/pack200 rt.jar.pack.gz rt.jar
解压缩命令unpack200 -r jre/lib/rt.jar.pack jre/lib/rt.jar
第三步将自己的程序打成jar包,注意指定主类,连同依赖的jar包一同放到jre/lib/ext下面,(当然也可以不怎么干,通过写批处理指定CLASSPATH)直接放到ext下面的好处在下面会体现出来
第四步 在jre文件夹的上层目录下面编写启动批处理%1的作用下面在说
@SET PATH=./jre/bin;%1;%PATH%;
@start javaw com.Main(根据实际情况修改为自己的程序入口)
将本地的jre或jdk文件夹重命名,并在cmd下敲java以确认本机的jre已经失效,点击批处理,测试如果程序正常启动的话,继续往下看,如果程序无法启动,将@start javaw com.Main改写为java com.Main重新启动调试下,看看是不是缺类.
第五步 将批处理编译成exe程序,使用Quick Batch File Compiler工具(http://www.abyssmedia.com/download.shtml),程序使用起来非常简单这里就不在介绍了,E文不好的可以去汉化新世纪下载中文的,注意如果要制作成安装包必须使用幽灵模式,不可以使用控制台模式.
第六步制作安装包使用InnoSetup工具(百度一下到处都有下载),此工具有使用向导,这部分就不介绍了,向导结束后,会提示生成脚本,保存此脚本并生成 exe安装包,运行安装包,如果生成出来的文件程序结构和第四步是一样的,并且可以运行的话,安装包制作完成.(这一步选择程序文件时批处理exe和 jre一同加进来注意jre必须是没有进行pack2000压缩的,否则需要在安装脚本里面另写解压程序)
第七步 随windows自动启动程序,修改安装脚本添加如下代码
[Registry]
Root: HKLM; Subkey: "SOFTWARE/Microsoft/Windows/CurrentVersion/Run"; ValueType: string; ValueName: "程序名"; ValueData: """{app}/主程序.exe"" ""{app}/jre/bin"""
这里面就用到了%1 熟悉批处理的同学都知道系统自启动的时候.代表的并不是程序的所在文件夹,所以这里传递了jre所在文件夹参数,@SET PATH=./jre/bin;%1;%PATH%;中把jre添加到了path中.
第八步注销下重新登录看看程序是否自动启动了.(可以在没有安装jre的机器上测试下)
我的安装包大小为10M左右,我依赖了很多第三方的jar包,否则还可以更小,最后还可以加个壳或使用rar压缩下
==================================================================================
Java5中带了一个压缩工具:Pack200,这个工具能对普通的jar文件进行高效压缩。其实现原理是根据Java类特有的结构,合并常数池,去掉无用信息等来实现对java类的高效压缩。由于是专门对Java类进行压缩的,所以对普通文件的压缩和普通压缩软件没有什么两样,但是对于Jar 文件却能轻易达到10-40%的压缩率。这在Java应用部署中很有用,尤其对于移动Java计算,能够大大减小代码下载量。
Java5中还提供了这一技术的API接口,你可以将其嵌入到你的程序中使用。使用的方法很简单,下面的短短几行代码即可以实现jar的压缩和解压:
压缩
Packer packer=Pack200.newPacker();
OutputStream output=new BufferedOutputStream(new FileOutputStream(outfile));
packer.pack(new JarFile(jarFile), output);
output.close();
解压
Unpacker unpacker=Pack200.newUnpacker();
output=new JarOutputStream(new FileOutputStream(jarFile));
unpacker.unpack(pack200File, output);
output.close();
更为详细介绍,请见下面的网址:
http://java.sun.com/javase/6/docs/technotes/guides/deployment/deployment-guide/pack200.html
==================================================================================
目前发布了一个swing 的程序,包括java web start 与applet 两个版本,但是由于第三方包的引入,发布包达到了近5MB,即使在局域网也让人无法忍受那缓慢的加载速度,毕竟对于绝大部分应用来说,网络带宽还是最终的系统瓶颈。
还好JDK5在Java Web Start和Java Plug-in中提供了对gizp和pack200压缩技术的支持,通过压缩将使Java的网络应用在jar的压缩基础上再一次的得到瘦身的飞跃。
gzip
jar包中包含的内容非Java类的资源文件比较多,例如JPEG, GIF等的,用gzip会比较合适
pack200
jar包绝大部分信息是class内容的话,那么pack200绝对是你的首选方案,因为pack200是专门针对class的java类进行优化设计的,主要体现在以下几个方面:
It merges and sorts the constant-pool data in the class files and co-locates them in the archive.
It removes redundant class attributes.
It stores internal data structures.
It use delta and variable length encoding.
It chooses optimum coding types for secondary compression.
压缩签名的整个发布过程
***/JDK5/bin/pack200 --repack demo.jar
--repack的作用等价与pack200和unpack200这两个指令,其作用是对demo.jar里面的class结构用Pack200的格式进行整理,因为签名需要根据jar包的类结构进行散列计算,所以如果不先进行jar的Pack200格式整理的话,等签名后再用pack200进行压缩将会导致签名无效,所以第一步需要进行--repack这个看似无用实则关键的操作
jarsigner -keystore myKeystore demo.jar ...
对Pack200格式整理过的demo.jar进行签名
***/JDK5/bin/pack200 demo.jar.pack.gz demo.jar
对签完名的demo.jar进行Pack200压缩,生成demo.jar.pack.gz
***/JDK5/sample/jnlp/servlet下面的jar包,主要是jnlp-servlet.jar拷贝到要发布的web工程的WEB-INF/lib/目录下
修改web发布工程的web.xml文件,将所有*.jnlp和*.jar的url路径定位到jnlp.sample.servlet.JnlpDownloadServlet进行处理
将demo.jar、demo.jar.pack.gz拷贝到jnlp或者applet指定的路径下
通过以上的操作一切就ok了,也许你想问jnlp和applet需要做什么改动吗,答案是no,一切都由JnlpDownloadServlet 进行透明处理了,jnlp和applet里面的指向还是demo.jar,JnlpDownloadServlet自动会根据request的 Accept-Encoding决定到底是下发demo.jar.pack.gz还是demo.jar,这样如果客户端安装了JDK5的Java Web Start或者Java Plug-in那么JnlpDownloadServlet自动会下发Pack200压缩的demo.jar.pack.gz包,如果客户端是JDK1.4或者更老的环境,那么JnlpDownloadServlet自然会下发demo.jar的普通包。
Pack200的压缩和解压缩速度是比较快的,而且压缩率也是很惊人的,在我是使用的包4.46MB压缩后成了1.44MB(0.322%),而且随着包的越大压缩率会根据明显,据说如果jar包都是class类可以压缩到1/9的大小。其实JavaWebStart还有很多功能,例如可以按不同的jar包进行lazy下载和单独更新,设置可以根据jar中的类变动进行class粒度的下载。心动不如行动,赶快去对你的发布程序进行瘦身吧。