一、准备工作
复制一份jre到新的路径。使用新jre的命令运行jar包,输出所有使用的类。
.\jre\bin\java.exe -jar -verbose:class javafx-start-1.0.jar >>class.txt
此步骤尽可能的点击使用所有的功能。
运行时可先精简bin目录。进入目录删除所有文件,提示占用的即不能删除的,其余都删除。
生成class.txt文件后,里边会提示打开什么jar包。此处以精简rt为例。
- /**
- * FileName: FileUtil
- * Date: 2022/9/16 16:54
- * Description:
- * History:
- */
- 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 aaa
- * @create 2022/9/16
- * @since 1.0.0
- */
- public class FileUtil {
-
- /**
- * @author soil
- */
-
-
- public static void main(String[] args) {
- // selectRtJar();
- getReplaceAllClass();
- }
-
- public static void getReplaceAllClass(){
- String sourse = "E:\\test/dytest/class_rt.txt";
- String outAddress = "E:\\test/dytest/class_demo2.txt";
- 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) {
- // 只读取以"[L"为开头的行
- 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();
- }
- }
-
- public static void selectRtJar(){
-
- String sourse = "E:\\test/dytest/class.txt";
- String outAddress = "E:\\test/dytest/class_rt.txt";
- FileInputStream fin = null;
- InputStreamReader isr= null;
- BufferedReader br= null;
- FileOutputStream fout= null;
- OutputStreamWriter osw= null;
- BufferedWriter bw= null;
- try{
- fin = new FileInputStream(sourse);
- isr = new InputStreamReader(fin);
- br = new BufferedReader(isr);
- // 输出文件位置
- fout = new FileOutputStream(outAddress);
- osw = new OutputStreamWriter(fout);
- bw = new BufferedWriter(osw);
- // 读一行
- String sp = br.readLine();
- // 只要没有读到文件尾就一直执行
- while (sp != null) {
- if (sp.contains("lib\\rt.jar")) {
- bw.write(sp + '\n');
- }
- sp = br.readLine();
- }
-
- }catch (Exception e){
- e.printStackTrace();
- }finally {
- try {
- if(br!=null){
- br.close();
- }
- if(bw!=null){
- bw.close();
- }
- if(osw!=null){
- osw.close();
- }
- if(fout!=null){
- fout.close();
- }
- if(isr!=null){
- isr.close();
- }
- if(fin!=null){
- fin.close();
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- }
-
- }
-
- }
首先使用第一个方法selectRtJar()挑选出所有使用rtjar的类。
在用第二个方法getReplaceAllClass();将所有的类路径转化删除多余最后输出一份斜杠形式的文件夹路径。
二、操作复制打包rt等
进入lib目录,解压rt.jar文件。
运行如下类方法:
- /**
- *
- */
-
- 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 aaa
- *
- */
- public class CopyClass {
- private String source = "E:\\test\\jre\\lib/"; // 类源目录
- private String dest = "E:\\test\\jre\\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"};
- CopyClass obj = new CopyClass("E:\\test/dytest\\jre\\lib/",
- "E:\\test/dytest\\jre\\lib/", jarArr);
- obj.readAndCopy("E:\\test/dytest/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 {
- 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;
- }
- }
改路径为自己的jre路径,运行之后会自动生成相关的rt1文件目录,如出现复制错误手动转移相关类。
进入rt1目录cmd。
运行命令 jar cvf rt.jar .
打包当前缩减后的jar,复制rt.jar到lib目录。
.\jre\bin\java.exe -jar javafx-start-1.0.jar
在此运行程序看是否可以执行。
如提示找不到main方法等,可以在复制java/lang,java/util,java/security这三个文件夹替换掉,如果还不行,再把sun/reflect,sun/misc,sun/security也替换掉!