JRE瘦身 & 制作小工具

目的:此前操作人员一直是用excel中的函数来进行一个业务数据的计算,由于此法操作不太方便,故应项目经理要求,用java写一个小工具,算法现成,只要能实现即可,于是写了一个html格式的,一个基于swing的exe文件,此文主要讲exe文件集成的jre瘦身。
但由于使用者的电脑环境中并未配置jre环境,所以我们在导出的exe文件中需集成jre,现在的我使用的jre1.8大小已经超过200M,而java文件却只有几百kb,有种头重脚轻的感觉,所以,对jre进行瘦身,删减掉没有用的文件是有必要的,删减后文件将不超过20M。
以下为正文:
本篇转载自:https://blog.csdn.net/xiaoping8411/article/details/6973887

打开JRE安装目录.目录包括bin,lib二个文件夹,所以就是将这两个文件进行瘦身了

  1. bin: 可以认为这是Java虚拟机.

  2. lib: 执行class文件时,Java虚拟机需要用到的类库及资源文件.

一、bin瘦身(瘦身之后大小约为5M)

方法为:

运行该exe文件,然后进入bin文件中,删除所有能删的,不能删除的系统会提示让重试;删完之后重新运行该工具,如果正常运行,那么bin文件就算搞定了。

二、lib的瘦身(重头戏,完成后大小约为10M)
① lib目录最主要的类库是rt.jar,是任意Java程序所必需的类库.
lib目录大约100MB,但是rt.jar类库就占了一半多,可见精简bin目录,最主要是裁剪rt.jar.

② lib目录下一个运行Java程序不可或缺的文件是位于i386下的虚拟机配置文件jvm.cfg.该配置文件用来管理不同版本的jvm.dll.其内容作为java.exe,javac.exe的全局变量,用来加载相应的动态链接库文件.

③ lib目录里面除了包含程序运行所需要的类库及配置文件外,还包含有一些诸如: 鼠标光标,字体等系统资源.简单程序如果未用到这部分资源的话,可以剔除.如果程序除去JRE部分,占用空间较大的话,为了避除资源加载错误带来的麻烦,建议保留这不到20MB的配置文件内容.

主要步骤如下:

1、提取我们需要的类库(jar),借助-verbose命令,查看虚拟机在运行Java程序时所加载的所有类,如:

@echo off
C:/Java/jdk1.6.0_16/bin/java -jar  -classpath lib/*.jar; -verbose:class printSoft.jar >> class.txt
pause

在class.txt文件中保存如下的信息:

[Loaded java.lang.Math from shared objects file]
[Loaded java.nio.charset.Charset$3 from C:\Java\jdk1.6.0_16\jre\lib\rt.jar]
[Opened C:\Java\jdk1.6.0_16\jre\lib\charsets.jar]
[Loaded sun.nio.cs.AbstractCharsetProvider from C:\Java\jdk1.6.0_16\jre\lib\rt.jar]
[Loaded sun.nio.cs.ext.ExtendedCharsets from C:\Java\jdk1.6.0_16\jre\lib\charsets.jar]
[Loaded java.lang.Class$1 from shared objects file]
[Loaded sun.reflect.ReflectionFactory$1 from shared objects file]
[Loaded sun.reflect.NativeConstructorAccessorImpl from shared objects file]

我们可以从class.txt中得到我们需要的jar文件和class文件,提交jar很简单,我就不说了,下面我们在看看如何提交我们用到的class文件:
由于class.txt每行都是形同: [Loaded java.lang.System from shared objects file]的一串字符,修改文本以方便获取类完整名java.lang.System,从而获得类似类路径java/lang/System的一串字符,方便后继编写类拷贝程序.
修改方法:
1. 查找并替换[Loaded 为空,达到删除[Loaded 的目的.
2. 使用任意一个具有正则表达式查找替换功能的文本编辑器,查找并替换 from.*为空,达到删除 from及其后面的字符串的目的.
3. 查找并替换.为/
4. 删除以[Opened 开头的行.
5. 删除程序中System.out.println的输出行.
提取之后class.txt就剩下如下信息:

java/lang/Object
java/io/Serializable
java/lang/Comparable
java/lang/CharSequence
java/lang/String
java/lang/reflect/GenericDeclaration
.......

2、从现有的jar包中提取我们整理的class文件,然后打包成jar,最终取代原有的jar,下面是一个提取class的工具类:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class CopyClass
{
    private String source = "C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\lib\\";      // 类源目录
    private String dest = "C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\lib\\";        // 类拷贝目的目录
    String[] jarArr = new String[]{"rt","charsets"};
    /***
     * 
     * @param source 类源目录
     * @param dest   类拷贝目的目录
     * @param jarArr 需要的提取的jar文件
     */
    public CopyClass(String source,String dest,String[] jarArr){
        this.source=source;
        this.dest=dest;
        this.jarArr=jarArr;
    }

    public static void main(String[] args)
    {
        String[] jarArr = new String[]{"rt","charsets"};
        CopyClass obj = new CopyClass("C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\lib\\",
                                                         "C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\lib\\",jarArr);
        obj.readAndCopy("C:\\Users\\lzp\\Desktop\\printSoft\\class.txt");
    }

    /***
     * @param logName 提取class明细
     */
    public void readAndCopy(String logName)
    {
        int count = 0;  // 用于记录成功拷贝的类数
        try
        {
            FileInputStream fi = new FileInputStream(logName);
            InputStreamReader ir = new InputStreamReader(fi);
            BufferedReader br = new BufferedReader(ir);

            String string = br.readLine();
            while(string != null)
            {
                if(copyClass(string) == true)
                    count++;
                else
                    System.out.println("ERROR " + count + ": " + string);
                string = br.readLine();
            }
        }
        catch (IOException e)
        {
            System.out.println("ERROR: " + e);
        }
        System.out.println("count: " + count);
    }

    /***
     * 从原jar路径提取相应的类到目标路径,如将java/lang/CharSequence类从rt目录提取到rt1目录
     * @param string 提取类的全路径
     * @return
     * @throws IOException
     */
    public boolean copyClass(String string) throws IOException
    {
        String classDir = string.substring(0,string.lastIndexOf("/"));
        String className = string.substring(string.lastIndexOf("/")+1,string.length()) + ".class";

        boolean result =false;

        for(String jar : jarArr){
            File srcFile = new File(source + "/"+jar+"/" + classDir + "/" + className);
            if(!srcFile.exists())
            {
                continue;
            }

            byte buf[] = new byte[256];
            FileInputStream fin = new FileInputStream(srcFile);

            /* 目标目录不存在,创建 */
            File destDir = new File(dest + "/"+jar+"1/" + classDir);
            if(!destDir.exists())
                destDir.mkdirs();

            File destFile = new File(destDir + "/" + className);
            FileOutputStream fout = new FileOutputStream(destFile);
            int len = 0;
            while((len = fin.read(buf)) != -1)
            {
                fout.write(buf,0,len);
            }
            fout.flush();
            result = true;
            break;
        }
        return result;
    }
}

然后在将提取的class文件打包成jar文件,利用jar命令进行打包,然后替换以前的jar文件,这样lib就从以前的六十多M到几M多有,如图:

大功告成,最后打包好交给操作人员即可。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值