当前位置:文档之家› JAVA打包称JAR怎么带上JRE

JAVA打包称JAR怎么带上JRE

让java程序带上精简的jre(附工具)java是跨平台的东西,但有的时候我们不需要它去跨平台,我们希望能想c++做的程序一样,编码和简单处理后能够在系统运行。

这次的项目是要放到classmate pc上,这款机器是为学生订做的,系统资源很有限,一个jre1.5就70多M,放在上面肯定是不行的。

于是我找了一些相关的资料,提供链接如下:如何制作最小的RCP程序压缩包(包含JRE)java程序发布之jre篇基本知道思路了,我把写的程序打包成jar,能双击运行了,然后拷贝一个jre到程序目录下,具体是这样的,目录叫dict,dict下面有dict.jar、jre(目录),然后写了一个cmd脚本:@echo offset path=%cd%\jre\binjava -jar -verbose:class dict.jar >>class.txtpause这样程序使用的就是当前目录下的jre,程序运行后,最好把所有的功能使用一遍,这样输出了一个文件class.txt,里面有所有需要的class,其格式如下:[Opened D:\data\dict\jre\lib\rt.jar][Loaded ng.Object from D:\data\dict\jre\lib\rt.jar][Loaded java.io.Serializable from D:\data\dict\jre\lib\rt.jar][Loaded parable from D:\data\dict\jre\lib\rt.jar][Loaded ng.CharSequence from D:\data\dict\jre\lib\rt.jar][Loaded poundFileReader$FileEntry from file:/D:/data/dict/dict.jar]我们依照这个文件来裁剪rt.jar:首先在utralEdit中进行一些处理,去掉所有不是rt.jar中的class的行,去掉from后面的,去掉loaded 等无关项目,再把“.”替换成“/”.这个可以利用正则表达式等轻松处理。

处理完后得到的文件类似如下格式:java/lang/Objectjava/io/Serializablejava/lang/Comparablejava/lang/CharSequencejava/lang/String然后写一个脚本或者程序处理,将rt中需要的的class拷贝到另一个对应的文件夹rt1,我用java写了一个,没有时间仔细改,但能完成人物了。

代码如下:import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.LineNumberReader;public class ReduceRt {//文件拷贝public static boolean copy(String file1,String file2){try //must try and catch,otherwide will compile error{// instance the File as file_in and file_outjava.io.File file_in=new java.io.File(file1);java.io.File file_out=new java.io.File(file2);FileInputStream in1=new FileInputStream(file_in);FileOutputStream out1=new FileOutputStream(file_out);byte[] bytes=new byte[1024];int c;while((c=in1.read(bytes))!=-1)out1.write(bytes,0,c);in1.close();out1.close();return(true); //if success then return true}catch(Exception e){System.out.println("Error!");return(false); //if fail then return false}}//读取路径,copypublic static int dealClass(String needfile ,String sdir,String odir) throws IOException {int sn = 0; //成功个数File usedclass = new File(needfile);if(usedclass.canRead()){String line = null;LineNumberReader reader = new LineNumberReader(new InputStreamReader(newFileInputStream(usedclass),"UTF-8"));while((line = reader.readLine())!=null){line = line.trim();int dirpos =stIndexOf("/");if(dirpos>0){String dir = odir+ line.substring(0,dirpos);File fdir = new File(dir);if(!fdir.exists())fdir.mkdirs();String sf = sdir + line + ".class";String of = odir + line + ".class";boolean copy_ok=copy(sf.trim(),of.trim());if(copy_ok)sn++;else{System.out.println(line);}}}}return sn;}public static void main(String[] args){String needfile = "usedclass.txt";String sdir = "./rt/";String odir = "./rt1/";try {int sn = dealClass(needfile,sdir,odir);System.out.print(sn);} catch (IOException e) {// TODO 自动生成 catch 块e.printStackTrace();}}}我裁剪出来的rt大小为500多k。

然后将rt1里面的目录和文件打包成rt.zip,改名为rt.jar,然后替换原来的rt.jar。

具体的步骤可以参考上面提到的那两篇文章。

#######################如何制作最小的RCP程序压缩包(包含JRE)Java开发程序,发布时总要考虑的问题就是怎么在使用者的机器上装好JRE。

要考虑的问题很多:使用者有没有能力独自安装JRE,使用者已有的 JRE 和我们需要的版本是不是一致,会不会出现版本问题,等等。

使用.NET要考虑的问题就少些。

现在.NET CLR似乎已经很普及了,看好多D版的 Win XP都会自己安装最新的.NET CLR,而且似乎它的安装界面也比JRE友好些。

彻底解决安装JRE的问题的方案,就是让我们的应用程序自己背着JRE!这样,我们的程序就像传统的Win32应用程序一样,双击就可以执行,不用管所在的机器上是否有JRE,是什么版本的JRE,无论怎样,我有我自己的!要做到这一点,其实非常容易。

王森在他的《Java深度历险》(强力推荐这本书,内容少而精)的第一章就解释了JDK,JRE,JVM之间的关系。

解释了我们执行java.exe时发生的事情。

其中提到,java.exe依照一套逻辑来寻找可以用的JRE,首先查找自己所在的目录下有没有 JRE(据王森讲这样说不确切,我没有JDK全部的源代码,在此无从考证);其次查找自己的父目录下有没有JRE;最后才是查询Windows的注册表。

通常我们在安装好了JRE的机器上的任何一个目录下都可以执行java.exe。

因为它在安装时被复制到了windows的system32目录下,而后者无论如何都会在path环境变量中。

这个java.exe最终必然会访问注册表来确定真正的JRE的所在地。

若我们要求每一个应用程序都自带JRE,必然不能走这条路。

但,逻辑的第二条讲,java.exe会在它的父目录下查找JRE,解决方案就在这一条中。

假设我们的应用程序打好了包,叫做 MyApp.jar,放在MyApp的目录下。

我们在MyApp目录下,可以执行java ?jar MyApp.jar来运行我们的程序。

我们安装的是 JRE 1.5,在C:\Program Files\Java\jre1.5.0下。

现在,我们只需要简单的将jre1.5.0目录搬到MyApp目录下,顺便改个容易写的名字比如叫jre。

现在,我们的应用程序就象这样:MyAppMyApp.jarJreJre1.5.0目录下的全部内容Java.exe 就在jre目录下的bin目录中。

根据第二条逻辑,java.exe会在它的父目录中查找jre,实验证实,它会查找lib目录,而lib就在jre目录下。

因此,这样java.exe就会确定jre的所在然后正常执行java程序,不会去管我们是否安装了JRE,注册表中是否有注册项这些杂事了。

试一下,在命令行下进入MyApp的目录下,假设它在C盘,将path指向MyApp下的JRE:set path=c:\MyApp\jre\bin然后运行:java ?verbose ?jar MyApp.jar加上verbose参数以确定我们确实用了这一套被搬出了家的JRE。

程序可以运行,并且在命令行输出的前几行,可以看到:[Opened C:\MyApp\jre\lib\rt.jar][Opened C:\MyApp\jre\lib\jsse.jar][Opened C:\MyApp\jre\lib\jce.jar][Opened C:\MyApp\jre\lib\charsets.jar]因此程序读取的确实是它的私有的JRE。

相关主题