一、准备工作
复制一份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;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @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也替换掉!