实测可用的精简jre的方法

对于一份不大的程序却要使用庞大的jre,这是一个很烦恼的事情,所以,在看了网络上千千万万的方法之后,终于测验并总结出可用的精简方法。
我jre精简前是这样的:
	![在这里插入图片描述](https://img-blog.csdnimg.cn/20200713173457564.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lfdHJ5,size_16,color_FFFFFF,t_70)	重点看bin文件夹以及lib文件夹。这两个是精简的重点,其他的皆可以舍弃。
桌面新建文件夹名: xin
复制你jre 以及 jar,并另外建文件夹tt。
将你的 rt.jar 解压到 xin 文件下。

一:精简bin

	对于bin文件夹的精简较为容易,将你程序的jar包放在bin目录下,cmd进入命令,输入`java.exe -jar xxx.jar`,运行后直接全选bin文件下所有,删除掉所有可以删除的对象,注意保留java.exe 以及javaw.exe,后者保障你的jre可以被你程序检索到,若是一直报no jvm found的错误,注意检查一下是否是这个文件错删了。
	测试重运行一下,可以将`java.exe -jar xxx.jar`以及后续的一些命令行操作改为批处理文件,省的每次都要重新处理。

一:精简lib

lib文件下最重要的是精简 rt.jar。至于其他的例如 charsets.jar,个人建议不要去动,避免出现资源加载错误。
将你的rt.jar 复制到一个单独的文件夹,解压缩后,在该目录新建一个文件夹命名tt,当然,此处是为了代码方便,这代码我也是网上摘抄的,但有些小错误,我已经修复了。

1.此处利用 -version 读出程序加载的类。

test.jar 注意改为你自己的jar
java -jar  -classpath lib/*.jar; -verbose:class test.jar >> class.txt

2.根据classes.txt文件提炼出具体的类包。


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * @author soil
 *
 */
public class Demo_Class2 {

    private static String sourse = "C:/Users/MY/Desktop/xin/class.txt";
    private static String outAddress = "C:/Users/MY/Desktop/xin/class_demo2.txt";

    public static void main(String[] args) {
        try {
            int count_L = 0;
            int loopCount = 0;
            // 源文件位置,打开它
            FileInputStream fin = new FileInputStream(sourse);
            InputStreamReader isr = new InputStreamReader(fin);
            BufferedReader br = new BufferedReader(isr);
            // 输出文件位置
            FileOutputStream fout = new FileOutputStream(outAddress);
            OutputStreamWriter osw = new OutputStreamWriter(fout);
            BufferedWriter bw = new BufferedWriter(osw);
            // 读一行
            String sp = br.readLine();
            // 只要没有读到文件尾就一直执行
            while (sp != null  ) {
                if (sp.length() < 1) {
                    System.out.println("发现一次!");
                }
                // 只读取以"[L"为开头的行
                else if (sp.substring(0, 2).equals("[L")) {
                    // 以空格来分隔这个行,返回的字符串数组中的第二个就是我们需要的信息
                    String s = sp.split(" ")[1];
                    StringBuilder bs = new StringBuilder(s);
                    // 只是个测试输出,可以不加
                    System.out.println(bs);
                    // 循环遍历这个字符串,修改它,使它变成我们需要的格式
                    for (int i = 0; i < bs.length(); i++) {
                        char ch = bs.charAt(i);
                        // 简化循环,因为我们得到的信息很有规律。只要出现大写的字母,就说明已经到了不需要执行的时候了。
                        if (ch >= 65 && ch < 91)
                            break;
                        // 把'.'替换成'/',当然,代码中是因为方法的参数要求。
                        if (ch == '.') {
                            bs.replace(i, i + 1, "/");
                        }
                        // 这个是循环的执行此时。
                        loopCount++;
                    }
                    // 这里在输出你的文件信息。加工后用于后续操作。
                    bw.write(bs.toString() + '\n');
                    // 程序需要的类文件数目。
                    count_L++;
                }
                // 读行
                sp = br.readLine();
            }
            // 两个测试输出
            System.out.println(count_L);
//            System.out.println(loopCount);
            // 千万要把两个文件关闭!!!
            br.close();
            bw.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.复制并分离这些class。

/**
 * Created by MY on 2020/7/6.
 */


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

/**
 * @author soil
 *
 */
public class CopyClass {
    private String source = "C:\\Users\\MY\\Desktop\\xin\\rt\\"; // 类源目录
    private String dest = "C:\\Users\\MY\\Desktop\\xin\\tt\\"; // 类拷贝目的目录
    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\\MY\\Desktop\\xin\\",
                "C:\\Users\\MY\\Desktop\\xin\\tt\\", jarArr);
        obj.readAndCopy("C:\\Users\\MY\\Desktop\\xin\\class_demo2.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();
            }
            br.close();
        } 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 {
        if (string.lastIndexOf("/") == -1) {
            return false;
        }
        String classDir = string.substring(0, string.lastIndexOf("/"));
        String className = string.substring(string.lastIndexOf("/") + 1, string.length()) + ".class";

        FileOutputStream fout;
        FileInputStream fin;
        boolean result = false;

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

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

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

            File destFile = new File(destDir + "/" + className);
            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;
    }
}

4.打包替换运行

在 tt 文件夹处进入cmd,运行以下代码

jar cvf rt1.jar -C rt\ .

修改名字为 rt ;放回 jre 并替换原有的jar包运行即可。

5.可能出现的错误
:1:对应确实什么class,到相应目录重新打包就好。
:2:显示什么 a JNA …类似的,或者是找不到main类似的,就是你的jre lib内的java少东西了,少什么我没有测出来,有个方法就是利用 GreenJVM,以下是我的网盘资源链接:
下载:
提取码:zu6a

按照操作将得出来的jar解压到你利用程序得出的jar综合以下,一般就可以用了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
精简jre步骤 1. 拷贝一个完整版的jre文件夹到D盘 2. 删除jre目录下所有出bin和lib目录的所有文件或目录 3. 打开cmd窗口,设置path路径为空,转到D:\jre\bin目录,运行java –version。正常显示当前Java的版本。 4. 在bin目录中新建一个temp目录,将除java.exe和java.dll外的移到temp目录中 5. 再次运行java –version命令,提示没找到verify.dll。将temp目录中的verify.dll移到bin目录中 6. 再次运行 java –version命令,提示:Could not create the Java virtual machine.错误 7. 根据测试:还要将hpi.dll和zip.dll放到bin目录中 8. 再次运行java –version命令,OK,又出现了版本信息。此时,可以将temp目录移出bin目录中。(放到桌面先) 9. 删除client目录中的除jvm.dll外的文件。转到jre目录,查看bin目录的大小,为2.89MB。但此时lib目录仍有60M有余 10. 转到lib目录,新建一个temp目录,将i386除外的目录都移动到temp目录中,再次运行java –version命令,OK 11. 再新建一个temp2目录,将charsets.jar和rt.jar外的所有文件移动到temp2目录中,再次运行 Java –version命令,OK 12. 将temp2和temp目录移到桌面。此时lib仍有48.7M接近50M。(还得努力) 13. 缩减charsets.jar和rt.jar(使用7z工具可以查看和修改jar文件的内容『直接添加和删除』)。准备做个软件来实现。 14. 缩减原则。运行java -verbose:class -version > temp.java 命令,此时在bin目录下生成了一个temp.java文件,用EditPlus打开,看到没有,要加载的就是那些类了,把不需要的全部删除就是了。 15. 原来charsets.jar没有加载呀。直接删除,再次运行java –version命令,OK 16. 接下来的工作就是裁剪rt.jar了。慢慢来。也可以做个软件来完成。可以下载一个GreenJVMMake.jar来完成。不过有时候好像有些类没加载到。要考虑更新了。 17. 裁剪玩rt.jar后,再次运行java –version ,出现了版本信息。OK 18. 转到D盘查看一下精简jre才4.47MB。不到5M。OK 19. 最小的jre制作完毕。 附带制作过程图片,可用Picasa来查看,播放模式效果更佳。 Thoams 2010-6-25 15:53

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值