常常在网上看到有人询问如何把java程序编译成exe文件通常回答只有两种一种是制作一个可执行的JAR文件包然后就可以像chm文档一样双击运行了而另一种是使用JET来进行
编译但是JET是要用钱买的而且据说JET也不是能把所有的Java程序都编译成执行文件性能也要打些折扣所以使用制作可执行JAR文件包的方法就是最佳选择了何况它还能保持Java的跨平台特性
下面就来看看什么是JAR文件包吧
JAR文件包
JAR文件就是JavaArchiveFile顾名思意它的应用是与Java息息相关的是Java的一种文档格式JAR文件非常类似ZIP文件准确的说它就是ZIP文件所以叫它文件包JAR文件与ZIP文件唯一的区别就是在JAR文件的内容中包含了一个METAINF/MANIFESTMF文件这个文件是在生成JAR文件的时候自动创建的举个例子如果我们具有如下目录结构的一些文件
==
`test
`Testclass
把它压缩成ZIP文件testzip则这个ZIP文件的内部目录结构为
testzip
`test
`Testclass
如果我们使用JDK的jar命令把它打成JAR文件包testjar则这个JAR文件的内部目录结构为
testjar
|METAINF
|`MANIFESTMF
`test
`Testclass
创建可执行的JAR文件包
制作一个可执行的JAR文件包来发布你的程序是JAR文件包最典型的用法
Java程序是由若干个class文件组成的这些class文件必须根据它们所属的包不同而分级分目录存放运行前需要把所有用到的包的根目录指定给CLASSPATH环境变量或者java命令的cp参数运行时还要到控制台下去使用java命令来运行如果需要直接双击运行必须写Windows的批处理文件(bat)或者Linux的Shell程序因此许多人说Java是一种方便开发者苦了用户的程序设计语言
其实不然如果开发者能够制作一个可执行的JAR文件包交给用户那么用户使用起来就方便了在Windows下安装JRE(JavaRuntimeEnvironment)的时候安装文件会将jar文件映射给javawexe打开那么对于一个可执行的JAR文件包用户只需要双击它就可以运行程序了和阅读chm文档一样方便(chm文档默认是由hhexe打开的)那么现在的关键就是如何来创建这个可执行的JAR文件包
创建可执行的JAR文件包需要使用带cvfm参数的jar命令同样以上述test目录为例命令如下
jarcvfmtestjarmanifestmftest
这里testjar和manifestmf两个文件分别是对应的参数f和m其重头戏在manifestmf因为要创建可执行的JAR文件包光靠指定一个manifestmf文件是不够的因为MANIFEST是JAR文件包的特征可执行的JAR文件包和不可执行的JAR文件包都包含MANIFEST关键在于可执行JAR文件包的MANIFEST其内容包含了MainClass一项这在MANIFEST中书写格式如下
MainClass:可执行主类全名(包含包名)
例如假设上例中的Testclass是属于test包的而且是可执行的类(定义了publicstaticvoidmain(String[])方法)那么这个manifestmf可以编辑如下
MainClass:testTest<回车>
这个manifestmf可以放在任何位置也可以是其它的文件名只需要有MainClass:testTest一行且该行以一个回车符结束即可创建了manifestmf文件之后我们的目录结构变为
==
test
Testclass
manifestmf
这时候需要到test目录的上级目录中去使用jar命令来创建JAR文件包也就是在目录树中使用==表示的那个目录中使用如下命令
jarcvfmtestjarmanifestmftest
之后在==目录中创建了testjar这个testjar就是执行的JAR文件包运行时只需要使用javajartestjar命令即可
需要注意的是创建的JAR文件包中需要包含完整的与Java程序的包结构对应的目录结构就像上例一样而MainClass指定的类也必须是完整的包含包路径的类名如上例的testTest而且在没有打成JAR文件包之前可以使用java<类名>来运行这个类即在上例中javatestTest是可以正确运行的(当然要在CLASSPATH正确的情况下)
jar命令详解
jar是随JDK安装的在JDK安装目录下的bin目录中Windows下文件名为jarexeLinux下文件名为jar它的运行需要用到JDK安装目录下lib目录中的toolsjar文件不过我们除了安装JDK什么也不需要做因为SUN已经帮我们做好了我们甚至不需要将toolsjar放到CLASSPATH中
使用不带任何的jar命令我们可以看到jar命令的用法如下
jar{ctxu}[vfmM][jar文件][manifest文件][C目录]文件名
其中{ctxu}是jar命令的子命令每次jar命令只能包含ctxu中的一个它们分别表示
c创建新的JAR文件包
t列出JAR文件包的内容列表
x展开JAR文件包的指定文件或者所有文件
u更新已存在的JAR文件包(添加文件到JAR文件包中)
[vfmM]中的选项可以任选也可以不选它们是jar命令的选项参数
v生成详细报告并打印到标准输出
f指定JAR文件名通常这个参数是必须的
m指定需要包含的MANIFEST清单文件
只存储不压缩这样产生的JAR文件包会比不用该参数产生的体积大但速度更快
M不产生所有项的清单(MANIFEST〕文件此参数会忽略m参数
[jar文件]即需要生成查看更新或者解开的JAR文件包它是f参数的附属参数
[manifest文件]即MANIFEST清单文件它是m参数的附属参数
[C目录]表示转到指定目录下去执行这个jar命令的操作它相当于先使用cd命令转该目录下再执行不带C参数的jar命令它只能在创建和更新JAR文件包的时候可用
文件名指定一个文件/目录列表这些文件/目录就是要添加到JAR文件包中的文件/目录如果指定了目录那么jar命令打包的时候会自动把该目录中的所有文件和子目录打入包中
下面举一些例子来说明jar命令的用法
)jarcftestjartest
该命令没有执行过程的显示执行结果是在当前目录生成了testjar文件如果当前目录已经存在testjar那么该文件将被覆盖
)jarcvftestjartest
该命令与上例中的结果相同但是由于v参数的作用显示出了打包过程如下
标明清单(manifest)
增加test/(读入=)(写出=)(存储了%)
增加test/Testclass(读入=)(写出=)(压缩了%)
)jarcvfMtestjartest
该命令与)结果类似但在生成的testjar中没有包含METAINF/MANIFEST文件打包过程的信息也略有差别
增加test/(读入=)(写出=)(存储了%)
增加test/Testclass(读入=)(写出=)(压缩了%)
)jarcvfmtestjarmanifestmftest
运行结果与)相似显示信息也相同只是生成JAR包中的METAINF/MANIFEST内容不同是包含了manifestmf的内容
)jartftestjar
在testjar已经存在的情况下可以查看testjar中的内容如对于)和)生成的testjar分别应该此命令结果如下
对于)
METAINF/
METAINF/MANIFESTMF
test/
test/Testclass
对于)
test/
test/Testclass
)jartvftestjar
除显示)中显示的内容外还包括包内文件的详细信息如
WedJun::GMTMETAINF/
WedJun::GMTMETAINF/MANIFESTMF
WedJun::GMTtest/
WedJun::GMTtest/Testclass
)jarxftestjar
解开testjar到当前目录不显示任何信息对于)生成的testjar解开后的目录结构如下
==
|METAINF
|`MANIFEST
`test
`Testclass
)jarxvftestjar
运行结果与)相同对于解压过程有详细信息显示如
创建METAINF/
展开METAINF/MANIFESTMF
创建test/
展开test/Testclass
)jaruftestjarmanifestmf
在testjar中添加了文件manifestmf此使用jartf来查看testjar可以发现testjar中比原来多了一个manifest这里顺便提一下如果使用m参数并指定manifestmf文件那么manifestmf是作为清单文件MANIFEST来使用的它的内容会被添加到MANIFEST中但是如果作为一般文件添加到JAR文件包中它跟一般文件无异
)jaruvftestjarmanifestmf
与)结果相同同时有详细信息显示如
增加manifestmf(读入=)(写出=)(压缩了%)
关于JAR文件包的一些技巧
)使用unzip来