让你的java程序飞起来

   “怎样才能把Java程序转化成为exe文件呢?”、“可用Java编写出Windows下的可执行程序吗?”这些都是在Java论坛上最常见的问题,在这些问题下边,通常有以下三种答案:
   1、不可能!
   2、何必呢,转化成exe就抹杀了Java“一次编译、到处运行”的理念。
   3、你可以用第三方软件,比如……
   我们为什么要把Java程序转换成exe文件呢?如果你遇到的问题,不用转化成exe也能搞定的话,你还需要exe文件吗?先来看看把Java程序转换为exe的目的吧。
  
  1、简化Java程序的部署
  
   把Java程序编译为平台独立的字节码(.class文件)后,还不能直接在我们的PC机上运行,还需要Java运行时环境(Java Runtime Environment,简称JRE),这个环境要么解释字节码指令,要么在运行时编译字节码为本机码(Native Code)。所以,想运行你的程序的用户,必须首先安装合适版本的JRE。否则,根本无法运行字节码。
   但是谁敢说所有用户都装了JRE,所有网吧都装了JRE,而且还装的是最新版本?有多少才学会上网的人懂得下载安装JRE?即使都安装了合适的JRE,链接运行Java程序的命令行指令也有点太长了,经常是这样的:
   java -Xmx200m -cp helloword.jar -Dsome.property MyApp
   当然了,你可以做一个包含这条语句的批处理文件,但是如果你要把程序给朋友、同事、老师看的话,还是一个整体的文件好些,而且还是双击就能运行的文件。或者更好,它可以像Windows体系中的程序一样,可以在控制面板里安装、卸载和更改配置。
   看来,把Java程序转化为exe的最基本动机就是可以简单地部署程序,让普通用户也可以顺利操作,如果仅仅是这个目的,那么可执行Java归档文件(Executable Jars)完全可以满足你的要求。
  
  2、可执行Jars(Executable Jars)
  
   你可以把Java程序打包到一个Jar包中,然后只要双击这个Jar包,就可以运行Java程序了,这比命令行方法,或者是批处理方法,更容易部署,更人性化。
   在你的类文件夹里,你必须再写一个manifest.MF文件,在这个文件中,你只要指定你的main class和其他用到的jar文件就可以了。
   然后就可以在本目录中生成jar文件,现在你可以在命令行中输入:
   java -jar MyApp.jar
   来直接运行你的程序了,在装有JRE的windonws环境中,你还可以直接双击来运行。在这个jar包中,Java类装载器从manifest.MF文件中获得要运行的main()方法。
   另外,如果你的程序包含了几个jar文件的话,是不是和许多class文件一样难以部署呢?这里给大家推荐一个开源工具One-JAR它可以把多个包重新打包成一个。下载地址是:
   http://one-jar.sourceforge.net/
   可执行jar包的主要问题是兼容性,用户的JRE环境可能是旧版本的,而你的程序却非要新版本不可,比如,你的程序使用Java 21.4版引入的Java.nio包,它不能在JRE 1.3及其以下的版本中使用。
   为了解决这个问题,Sun公司使用了最新的程序部署技术——Java Web Start,这个新技术有效解决了程序的兼容性问题,并且还加入了很多新特性,从1.4版开始,它已经是Java 2平台的一部分。
  
  3、Java Web Start
  
   Java Web Start(JWS)和它的底层协议Java Network Launch Protocol(JNLP)使我们的Java程序可以从网络服务器上发行,终端用户仅仅点击一下网页链接就可以初始化Java程序的安装。Java程序被装载后,这个程序将驻留在用户系统中,所以下次用户点击同样的链接时,如果计算机是脱机的或者程序没有更新,那么JWS引擎会从缓存启动这个Java程序的本地副本,这将大大加快Java程序的启动速度。
   JWS的另一个特性是,它在沙箱中运行程序,沙箱是基于Java安全构架的限制性容器。但是,和Java Applet不同的是,Java程序会提示用户,并且得到允许后,可以访问本地系统资源,比如文件系统、打印机和系统剪贴板。
   但是JNLP也是有缺点的,为了和浏览器的无缝结合,浏览器和包含JNLP程序的主机必须支持application/x-Java-jnlp-file MIME类型。某些主机是不能支持的。而且,版本变更和不断的升级要求主机的附加支持,这就需要加入Servlets和Cgi-bin脚本等等。
   JNLP对程序处理时,可能会稍微改变程序代码,并且重新打包到一系列jar文件中。
   JWS比较适合受控系统(Controlled Environment),比如企业内部互联网(Corporate Intranet),但是不适合广大的消费市场,在消费市场中,你最好使用自定义的Java启动程序和打包程序(Custom Java Launchers And Wrappers)。
  
  4、自定义的Java启动程序和打包程序(Custom Java LaunchersAndWrappers)
  
   当Java程序以上述任何一种方式启动时(批处理,可执行Jars或JWS),系统就会从JRE中启动一个Java启动程序,Windows版本的JRE已经这样区分它们,使用控制台的Java程序启动java.exe,使用图形界面的应用程序启动javaw.exe。
   所以,所有运行着的Java应用程序拥有同样的任务栏和Alt-Tab图标,并且在Windows任务管理器中,仅仅显示Java.exe或者Javaw.exe。如果你同时运行几个Java程序的话,你是无法在任务管理器中区分它们的。
   实际上,那些启动程序是本地程序,它们从DLL或者共享库中启动Java虚拟机,并且使用特殊的API使JVM运行你的程序。这些API是Java本地接口JNI(Java Native Interface)的一部分,标准化而且使用简单,通过它你可以为你的启动程序指定自己的名字和图标。它要做的仅仅是在终端用户操作系统找到合适的JRE,除非你在你的程序中绑定了JRE。否则这个合适的JRE就会初始化JVM,并且运行你的程序。
   如果你没有工具、技巧或时间来为你的程序自定义启动程序,你可以使用第三方软件帮助你生成启动程序。
   最值得我们注意的还是程序的打包(Wrapping),Java包装器(Wrapper)本质上是个自定义的启动器,而且还是一个包含所有class文件、jar文件和附加文件的自解压包。包装器在程序启动时解压这些文件,在程序结束时删除这些文件。这样一来,你的程序就是一个可执行的包了。
   包装器在它启动前寻找JRE,如果JRE还没有安装,或者版本不符合程序的兼容性要求,一些包装器就会安装JRE。如果你把合适的JRE打包到程序中,它会直接安装;如果没有,它会提示用户下载安装。
   最好用的包装器会为你建立文件关联,在第一次安装时创建桌面快捷方式。但是,对于一个彻底的应用软件,这都是很不够的,比如你的程序支持自动更新,或者统一的跨平台支持,那怎么办呢,你应该使用:兼容Java的安装程序生成器(Java-Aware Setup Authoring Tools)。
  
  5、兼容Java的安装程序生成器(Java-Aware Setup Authoring Tools)
  
   如果你所需要的是一个绑定了JRE的Java程序,那么你可以使用任何安装程序(setup.exe)生成器。而且使用一个兼容Java程序的安装程序生成器还有一些好处:
   (1) 可以在安装时进行JRE检测,下载并且安装。
   (2) 可以生成本地启动程序。
   (3) 用户可以自己编辑JVM参数文件。
   (4) stderr和stdout重定向可以使你保存日志文件(logs)和栈溢出信息。
   (5) 可以应用Java程序为Windows服务或者Unix后台服务。
   根据定价和功能的不同,有很多可选的生成器,我们来逐一分析:
   面向Windows平台的工具:比如Advanced Installer for Java。使用它,你可以制作.MSI(Windows Installer)安装文件。
   面向多平台的工具:它可以为Windows、Linux和Mac OS X生成本地安装文件,比如Install4j就是其中之一。
   还有很多基于Java的安装程序生成器,可以帮助你创建跨平台的安装文件,这些安装程序本质上都是可执行jars,InstallAnywhere可能是这类工具中最出名的,但是它不是免费软件,你还可以考虑较便宜的JExpress和开源软件IzPac。
   所有上述的结论都不改变一个原则:无论你创建一个可执行jar或者是创建一个精心设计的安装程序,你的Java程序仍然是平台独立的字节码。以前,在普通PC上执行Java程序的唯一途径是解释这些字节码。现在,J2SE包含Just-In-Time(JIT)编译器,它可以把经常执行的方法转化为本地码(Native Code)。所以,如此更进一步的话,就应该在执行之前,把整个应用程序转化为本地码,已经有软件实现了这点,他们是Ahead-Of-Time编译器。
  
  6、Ahead-Of-Time编译器
  
   Ahead-Of-Time编译器把你的jar文件和class文件,为特定的目标平台,转化成本地码,比如转化为Windows的exe文件,或者Linux的ELF文件。但是,就像前面的软件或者方法一样,它也有优点和缺点。
   优点:
   (1)性能。JIT编译器在程序运行时工作,并且和所编译的程序及所有正在运行的程序分享CPU和内存,而AOT编译器编译的程序直接运行,没有资源浪费,没有编译时间限制,所以它能潜在地做更多的资源优化。
   (2)知识产权的保护。Java字节码是很容易被反编译的,逆向工程网站上的反编译工具多如牛毛。或许你可以使用混淆共有类的名称和方法来避免反射机制,但是这又有潜在的危险,未来的虚拟机可能不能运行混淆过的代码,或者会阻止JIT编译器的优化。还有,不管你用什么加密算法,还是无法彻底保护Java字节码!
   相反,AOT编译器产生的本地码是极难被逆向工程的,就像你的源代码是C++一样。而且,转化为本地码不像混淆那样会产生性能缺失。如果你很关心你的知识产权,那么你应该考虑本地码编译器!
   (3)用户的感觉。Java程序总是给人感觉需要“预热”一样。想想看,启动一个Java程序,你需要先启动字节码解释器解释class文件,接着进行性能剖析(Profiling),然后是JIT编译器编译。所以Java程序感觉总是比较慢。
   但是,本地码可以直接与操作系统接触,避免了解释-剖析-编译的过程,所以它会快得多,拥有最佳的反应速度。
   缺点:
   (1)占用磁盘空间多。Java字节码是很紧凑的,它的指令集比CPU指令集要高级得多。这样一来,一个AOT产生的可执行文件是原始jar文件的2~4倍大小。
   (2)动态应用方面。应用程序在运行时动态装载的类可能会给AOT带来麻烦,AOT可能不能装载它们。这些动态装载的类包括第三方插件、动态代理和其它在运行时生成的类。所以,这类程序在运行时系统必须包含字节码解释器和JIT编译器。
   (3)针对硬件的优化。JIT编译器对于AOT编译器来说,有一个潜在的优势,那就是JIT可以针对不同的硬件选择不同的代码模式。比如,它会使用Intel系列CPU的MMX/SSE/SSE2来加快浮点运算。AOT编译器必须要么仅仅为CPU最一般的特性来产生代码,要么针对CPU密集型的程序开发多个版本。
   有一个误解是AOT编译器抹杀了Java程序的可移植性(Portability),其实不然,因为源代码并没有为此而改变,所以你可以随时在非AOT环境中部署你的字节码程序。  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值