工程打包
无论是什么IDE,打包都是一件十分简单的事。(这里不讨论自己手动打包的情形)
jar包的运行
如果环境变量中以及添加了jre的路径,那么java的执行如下:
1 | $ java -jar xxx.jar arg1 arg2 XXX |
如果不想每次都使用命令行来输入的话,就可以把上面的命令变成一条bat
脚本:
例如取名加start.bat
,内容为:
1 | @echo off |
其中@echo off
意思为不打印输出,start
意味着新建窗口执行后面的命令,pause
表示暂停,
也就是可以在运行结束时出现请按任意键继续...
,另外%1 %2
表示两个输入参数。
注意:此时jar包的路径就是它的执行路径,有时候程序可能需要取这个路径来进行相对路径的写操作, java中可以使用下面语句来取到:
1
System.getProperty("user.dir")
1 | System.getProperty("user.dir") |
jre不添加环境变量运行
上面考虑的是环境变量中以及添加了jre的情况,有时候我们可能需要把程序放到别的电脑上来运行, 这时候如果别人的电脑上没有java环境,那就会执行不了,总不能让别人现装一个吧。
考虑到最大化的简便使用者,就需要把jre拿出来,和jar包绑在一起发送给别人。
那么如何使用jre来直接运行java呢?使用jre中bin下的java.exe或者javaw.exe即可:
1 | $ .\jre\bin\java -jar xxx.jar arg1 arg2 ... |
它两之间没有什么不同,javaw
会屏蔽打印信息,而java
不会。
那么现在,就只需要将jre放到jar包同一个目录下,使用上面的命令就可以运行程序, 这样就能在没有java环境的电脑上运行,因为我们自带了java运行环境。
这里具体的目录结构当然不重要,看个人喜好了。
精简jre
这里使用的是jre 1.8
,从jdk-8u131
下取出来的,大小为188M。
显然,相比于我的程序来说,这实在是太大了,如果不精简jre,整个程序包就得有近200M, 这有一点不能接受,所以还是需要精简jre。
这里我参考了博客整理JRE瘦身或精简JRE
那么有没有一些精简工具呢?
搜索了半天,有一个greenvm,但是这程序好像已经非常久没有更新了, 这位作者是不是放弃它了,下载下来试了一下,好像有一点问题,总之我用的时候是报错了。
还有一个jrecreate,这个是oracle
公司官方的,不过好像不是针对某个程序设计的?感觉就是提供了几个较小版本的jre?有待考证。
感觉大部分网友还是自己手动进行精简,那么如果要手动精简,首先整理几个点:
- jre文件下需要考虑的就是两个文件夹
bin
和lib
。 bin
文件夹下总的文件数不多,体积大概为80M,其中大部分东西都用不到。lib
文件夹下有很多文件,体积大概有100M,其中有少量的jar包会用到。
有了上面几个点,下面就是第一步精简的策略:
首先对于bin
文件夹的精简策略:
- 手动删除几个文件,然后执行jar包,看是否报错,就这样精简到不能再精简。
想着手动挺烦的,但是其实上这里大部分文件都可以删除,而且文件也不多,几分钟就能清理完毕。 (我清除完就剩下8M,主要是jvm.dll比较大)。
第二,对于lib
文件夹的精简策略:
- 同样的,手动删。
- 这里可能需要留的文件比较多,所以建议直接按文件大小,很多小文件(1KB,2KB)就不用删了,试一试删除一些大文件。
我这里最后剩下两个较大的文件charsets.jar
和rt.jar
,那么加起来还是有60M多,恩,还需要继续精简。
精简charsets.jar和rt.jar
charsets.jar
和rt.jar
中有很多程序运行时需要调用的class文件,所以我们删不掉它们,那么很明显,
只要将程序不用的class文件从中删去,就能减小大小。
要这样做,首先就得知道自己的程序在运行过程中使用了哪些类,可以使用下面命令来打印:
1 | $ java -jar -verbose:class XXX.jar |
这样就能打印我们使用了哪些类,将这些信息重定向到文件中:
1 | $ java -jar -verbose:class XXX.jar >> class.txt |
那么这里就得到了class.txt
,其中以[Load ...]
开头的就是在加载类。
进一步,我们要将charsets.jar
和rt.jar
类中的相关class提取出来:
- 将这两个文件给解压缩了,得到
charsets
,rt
文件夹。 - 编写代码,取到
class.txt
中加载的类,对比的去charsets
,rt
文件夹中找,找到就复制到新文件夹。
这里的代码会附加到最后面,总之,这里得到两个新的charsets
,rt
文件夹,下面已经去除了不需要的class文件。
直接将这两个文件夹用zip打包(不要将charsets或者rt文件夹也给包了,这样就比原来的jar包多了一层目录了),改名为charsets.jar
和rt.jar
,放回jre所在的位置中替换既可。
这样下来lib
文件夹可以缩小到10M以下。
讲道理应该是可以的,但是我这里报错了,可能是我个人的问题。
实际上的精简操作
由于上面的方法最后在运行jar包时报错了,所以我手动添加了一些class回去。
事实上,对于charsets.jar
,我没有改动内容,只是将它解压重新用zip压缩了一遍,这样的确可以缩小一点。
对于rt.jar
,我将java和sun两个包下的类都保留了,因为不知道到底少了哪个class。
最终jre的大小精简到22M。
问题
不知道在后面的使用中还会不会有别的问题。
2018-06-15:使用时问题,我程序中需要有输入文件,输入文件的格式可能是.xml
、.xls
、.xlsx
、.csv
,
但是在精简的时候我只使用了.csv
文件测试,于是当输入文件变成.xls
格式时,就出现了问腿。
所以,在不得已的时候还是不要尝试使用本方法精简jre,由于程序运行过程的变化,可能会出现问题。当然, 如果程序比较简单,没什么变化时,还是可以精简jre的。
代码
参考了整理JRE瘦身或精简JRE,进行了少量改动。
jarInputPath
是输入文件夹,这里下面就有两个文件夹rt、charsets。(解压了的)
jarOutputPath
是输出文件夹。
jarPackNames
就是两个包名。
classListInputPath
就是上面命令打印出来的信息。
classListOutputPath
所有这里复制了的类的名字会保存到这个文件中。
另外:输入文件与输出文件的编码注意一下。
1 | import java.util.ArrayList; |