精简JAVA-JRE备忘录

简介: 精简JAVA-JRE备忘录

精简过的JRE一般都不是通用的,都是针对自己的应用程序把不需要的类去掉,从而达到精简目的。所以有些人想拿别人精简过的JRE运行自己的应用程序,这样是不靠谱的。最后还是得自己动手精简,过程也挺简单。

思路:

把自己的应用程序打包成jar,然后通过jar命令运行这个jar,把jar所需的类全部打印到一个文本文件里面,把文本文件里面的类提取出来,重新打包。覆盖JRE目录中的JAR包。去掉JRE下bin目录和lib目录中不需要得。瘦身完成。

 

应用程序打包后是test.jar,jre(目录) 也和它同一文件夹,写一个test.bat脚本方便测试:

@echo off
java -jar -verbose:class test.jar >>class.txt
@pause


程序运行后,最好把所有的功能使用一遍,这样输出了一个文件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]
....


总共会有3个jar包用到,/jre7/lib/ext/localedata.jar,/jre7/lib/rt.jar,/jre7/lib/charsets.jar, 把 class.txt 分拆成localedata.txt,rt.txt,charsets.txt,在notepad中进行一些处理,去掉所有不是rt.jar中的class的行(搜索,标记,删除书签行),去掉from后面的( from.+?$),去掉loaded等无关项目,再把“.”替换成“/”.这个可以利用正则表达式等轻松处理。

处理完后得到的文件类似如下格式:

rt.txt

java/lang/Object
java/io/Serializable
java/lang/Comparable
java/lang/CharSequence
java/lang/String


我们再依照这个文件来裁剪charsets.jar,localedata.jar,

然后写一个程序处理,从rt或charsets中把需要的的class拷贝到另一个对应的文件夹rt1或charsets1。在运行下面JAVA程序之前需要将JRE目录中localedata.jar,rt.jar,charsets.jar分别解压到相应目录。


所需的类都抽取到rt1目录之后,把原rt目录中的“META-INF”文件夹拷贝到rt1下面,进入rt1目录,用rar压缩工具打包成rt.zip,改名为rt.jar,然后替换jre6/lib目录下的rt.jar。

charsets1目录处理同上。

 

package test;
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) {
      e.printStackTrace();
      // 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 = "E:/fishing/3.program/server/trunk/test/src/test/localedata.txt";// 运行JAR生成的,应用程序所需类的txt文件
    String sdir = "E:/fishing/3.program/server/trunk/test/res/ext/localedata/"; // rt.jar解压后的目录
    String odir = "E:/fishing/3.program/server/trunk/test/res/ext/localedata1/";// 抽取的类存放目录
    try {
      int sn = dealClass(needfile, sdir, odir);
      System.out.print(sn);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}


所需类的精简工作已经完成,接下来精简其他的。

 

1、Jre目录下的license都删除,只留bin和lib目录

2、bin下的执行文件需要运行jar时用DLL_Killer工具查看使用到了哪些文件

3、lib下只要保留 rt,charsets库就可以了(因为应用程序只用到了这两个)。

4、除了i386和zi两个子目录外,其余的子目录都可以不要(原则上都要自己试试看删除其他目录会不会报错)。

5、Zi下只需要保留自己地区的子目录和其下的一些文件就可以(这里Zi下我只保留了America文件夹)。

6、Lib下除了库之外的属性文件都要保留。


PS: 抽取出的类重新打包成rt.jar时要注意,用JAR命令和rar工具打的jar包都不行。解决如下:

-将原生的rt.jar用rar打开,然后进入相关目录,删除掉相关目录或者文件,再把抽取出来的类拖进来就行了。

 

优化完成!

目录
相关文章
|
7月前
|
Java 编译器 测试技术
滚雪球学Java(03):你知道JDK、JRE和JVM的不同吗?看这里就够了!
【2月更文挑战第12天】🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!!
144 4
|
7月前
|
监控 安全 Java
探索Java的未来:JDK 18新特性全览
探索Java的未来:JDK 18新特性全览
267 0
|
移动开发 Java 开发工具
3.JAVA为什么能这么火?---了解Java语言的发展,功能,跨平台的原理以及什么是JDK,JRE
3.JAVA为什么能这么火?---了解Java语言的发展,功能,跨平台的原理以及什么是JDK,JRE
92 1
|
2月前
|
开发框架 Oracle Java
【编程基础知识】《Java 世界探秘:JRE、JDK 与 JDK 版本全解析》
JRE(Java Runtime Environment)是运行Java程序所需的环境,包含JVM和Java核心类库,适合普通用户使用。JDK(Java Development Kit)则是Java开发工具包,不仅包含JRE,还提供了编译器、调试器等开发工具,适用于开发者。两者的主要区别在于JDK用于开发,而JRE仅用于运行Java程序。JDK各版本不断引入新特性,如Java 8中的Lambda表达式和默认方法等。环境配置方面,Windows和Linux系统都有详细的步骤,确保Java程序能够顺利编译和运行。
58 1
|
7月前
|
Java
【Java开发指南 | 第二十一篇】Java流之文件
【Java开发指南 | 第二十一篇】Java流之文件
55 0
|
4月前
|
Java 编译器 测试技术
Java零基础教学(03):如何正确区别JDK、JRE和JVM??
【8月更文挑战第3天】Java零基础教学篇,手把手实践教学!
72 2
|
7月前
|
小程序 Java 程序员
【Java探索之旅】我与Java的初相识(二):程序结构与运行关系和JDK,JRE,JVM的关系
【Java探索之旅】我与Java的初相识(二):程序结构与运行关系和JDK,JRE,JVM的关系
82 0
|
存储 Java 程序员
|
Oracle 安全 Java
Java 8 - JRE精简
《基础系列》
259 1
Java 8 - JRE精简
|
缓存 Java 程序员