为指定java应用程序进行jre廋身
来源:互联网 发布:java配置环境变量 编辑:程序博客网 时间:2024/05/16 00:29
参考文章:
http://glemir.xplore.cn/archives/200
http://blog.csdn.net/nsrainbow/archive/2008/04/26/2333206.aspx
这里结合参考的文章和网上的一些JRE瘦身经验说下我精简JRE的过程。
精简过的JRE一般都不是通用的,都是针对自己的应用程序把不需要的类去掉,从而达到精简目的。所以有些人想拿别人精简过的JRE运行自己的应用程序,这样是不靠谱的。最后还是得自己动手精简,过程也挺简单。
思路:
把自己的应用程序打包成jar,然后通过jar命令运行这个jar,把jar所需的类全部打印到一个文本文件里面,把文本文件里面的类提取出来,重新打包。覆盖JRE目录中的JAR包。去掉JRE下bin目录和lib目录中不需要得。瘦身完成。
应用程序打包后是test.jar,jre(目录) 也和它同一文件夹,写一个CMD脚本方便测试:
- @echo off
- set path=./jre6/bin
- java -jar -verbose:class test.jar >>class.txt
- pause
@echo offset path=./jre6/binjava -jar -verbose:class test.jar >>class.txtpause
这样程序使用的就是当前目录下的jre,程序运行后,最好把所有的功能使用一遍,这样输出了一个文件class.txt,里面有所有需要的class,其格式如下:
- [Opened D:\data\dict\jre\lib\rt.jar]
- [Loaded java.lang.Object from D:\data\dict\jre\lib\rt.jar]
- [Loaded java.io.Serializable from D:\data\dict\jre\lib\rt.jar]
- [Loaded java.lang.Comparable from D:\data\dict\jre\lib\rt.jar]
- [Loaded java.lang.CharSequence from D:\data\dict\jre\lib\rt.jar]
- [Loaded org.apache.lucene.index.CompoundFileReader$FileEntry from file:/D:/data/dict/dict.jar]
[Opened D:\data\dict\jre\lib\rt.jar][Loaded java.lang.Object from D:\data\dict\jre\lib\rt.jar][Loaded java.io.Serializable from D:\data\dict\jre\lib\rt.jar][Loaded java.lang.Comparable from D:\data\dict\jre\lib\rt.jar][Loaded java.lang.CharSequence from D:\data\dict\jre\lib\rt.jar][Loaded org.apache.lucene.index.CompoundFileReader$FileEntry from file:/D:/data/dict/dict.jar]
输出的class文件里面可能还包含其他应用的jar包,如:charsets.jar。这样就需要把class文件里面的信息按rt和charsets分成两类分别放到两个txt文件里面:rt_class.txt,charsets.txt
我们依照这个文件来裁剪rt.jar:
首先在utralEdit中进行一些处理,去掉所有不是rt.jar中的class的行,去掉from后面的,去掉loaded等无关项目,再把“.”替换成“/”.这个可以利用正则表达式等轻松处理。处理完后得到的文件类似如下格式:
rt_class.txt
- java/lang/Object
- java/io/Serializable
- java/lang/Comparable
- java/lang/CharSequence
- java/lang/String
java/lang/Objectjava/io/Serializablejava/lang/Comparablejava/lang/CharSequencejava/lang/String
我们依照这个文件来裁剪charsets.jar:
首先在utralEdit中进行一些处理,去掉所有不是charsets.jar中的class的行,去掉from后面的,去掉loaded等无关项目,再把“.”替换成“/”.这个可以利用正则表达式等轻松处理。处理完后得到的文件类似如下格式:
charsets.txt
- sun/nio/cs/ext/ExtendedCharsets
- sun/nio/cs/ext/GBK
- sun/nio/cs/ext/DoubleByteDecoder
- sun/nio/cs/ext/GBK$Decoder
- sun/nio/cs/ext/DoubleByteEncoder
- sun/nio/cs/ext/GBK$Encoder
sun/nio/cs/ext/ExtendedCharsets sun/nio/cs/ext/GBK sun/nio/cs/ext/DoubleByteDecoder sun/nio/cs/ext/GBK$Decoder sun/nio/cs/ext/DoubleByteEncoder sun/nio/cs/ext/GBK$Encoder
然后写一个脚本或者程序处理,从rt或charsets中把需要的的class拷贝到另一个对应的文件夹rt1或charsets1,这里参考网上的一个JAVA抽取程序。
在运行下面JAVA程序之前需要将JRE目录中rt.jar,charsets.jar分别解压到相应目录
代码如下:
- package com.ccic.greenjvm;
- 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_out
- java.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
- }
- }
- // 读取路径,copy
- public 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(new FileInputStream(usedclass),
- "UTF-8"));
- while ((line = reader.readLine()) != null) {
- line = line.trim();
- int dirpos = line.lastIndexOf("/");
- 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 = "D:/greanjvm/rt_class.txt";//运行JAR生成的,应用程序所需类的txt文件
- String sdir = "D:/greanjvm/rt/"; //rt.jar解压后的目录
- String odir = "D:/greanjvm/rt1/";//抽取的类存放目录
- try {
- int sn = dealClass(needfile, sdir, odir);
- System.out.print(sn);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
package com.ccic.greenjvm;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(new FileInputStream(usedclass),"UTF-8"));while ((line = reader.readLine()) != null) {line = line.trim();int dirpos = line.lastIndexOf("/");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 = "D:/greanjvm/rt_class.txt";//运行JAR生成的,应用程序所需类的txt文件String sdir = "D:/greanjvm/rt/"; //rt.jar解压后的目录String odir = "D:/greanjvm/rt1/";//抽取的类存放目录try {int sn = dealClass(needfile, sdir, odir);System.out.print(sn);} catch (IOException e) {e.printStackTrace();}}}
所需的类都抽取到rt1目录之后,把原rt目录中的“META-INF”文件夹拷贝到rt1下面,进入rt1目录,用rar压缩工具打包成rt.zip,改名为rt.jar,然后替换jre6/lib目录下的rt.jar。
charsets1目录处理同上。
所需类的精简工作已经完成,接下来精简其他的。
1、Jre目录下的license都删除,只留bin和lib目录
2、bin下的执行文件需要运行jar时用DLL_Killer工具查看使用到了哪些文件
3、lib下只要保留 rt,charsets库就可以了(因为应用程序只用到了这两个)。
4、除了i386和zi两个子目录外,其余的子目录都可以不要(原则上都要自己试试看删除其他目录会不会报错)。
5、Zi下只需要保留自己地区的子目录和其下的一些文件就可以(这里Zi下我只保留了America文件夹)。
6、Lib下除了库之外的属性文件都要保留。
优化完成!!!!!!!!!!!
注意事项:
1、精简BIN目录
*运行JAR包时需指定PATH路径,不然会默认搜索环境变量中的JDK路径。
*用DLL_Killer工具查看任务管理器中java.exe调用的DLL库
2、精简LIB目录
*抽取出的类重新打包成rt.jar时要注意,用JAR命令和rar工具打的jar包都不行。解决如下:
-将原生的rt.jar用rar打开,然后进入相关目录,删除掉相关目录或者文件,再把抽取出来的类拖进来就行了。
*zi文件夹下只留America文件夹
- 为指定java应用程序进行jre廋身
- 批处理文件指定jre路径启动java桌面应用程序
- java解决指定应用程序打开指定文件
- Java:为jre添加SSL证书
- 为应用程序池指定标识 (IIS 7)
- 如何让java运行在指定版本的JRE中
- java 指定打印机 进行打印
- JAVA 指定打印机进行打印
- java 指定打印机 进行打印
- java 指定打印机 进行打印
- java 指定打印机 进行打印
- java 指定打印机 进行打印
- Ecliplse 指定JRE
- tomcat指定jre、jdk
- Ecliplse 指定JRE
- 为Eclipse指定Java VM
- 为java应用程序设置代理
- JAVA应用程序转换为Applet
- DLL编写教程
- [Android开发] 代码code设置9.png/9-patch 图片背景后,此view中的TextView等控件显示不正常(常见于listview中)
- 使用Eclipse调试Sqlite
- 大型网站的监控、报警与故障转移
- awk 初步
- 为指定java应用程序进行jre廋身
- nodeValue以及其与value的区别以及JS nodeName、nodeValue、nodeType返回类型
- ubuntu 下使用webmin配置vpn
- Android ListView 滑动背景为黑色的解决办法
- 为什么我们程序员难晋升
- [Android实例] Android 使用HttpClient访问https
- [Android实例] Android 实例SOCKET发送HTTP请求
- Android流量统计TrafficStats类的使用
- 面试为什么要设多位面试官?