• jre精简配合java的桌面小工具打包


    一、准备工作

    复制一份jre到新的路径。使用新jre的命令运行jar包,输出所有使用的类。

    .\jre\bin\java.exe -jar -verbose:class javafx-start-1.0.jar >>class.txt

    此步骤尽可能的点击使用所有的功能。

    运行时可先精简bin目录。进入目录删除所有文件,提示占用的即不能删除的,其余都删除。

    生成class.txt文件后,里边会提示打开什么jar包。此处以精简rt为例。

    1. /**
    2. * FileName: FileUtil
    3. * Date: 2022/9/16 16:54
    4. * Description:
    5. * History:
    6. */
    7. import java.io.BufferedReader;
    8. import java.io.BufferedWriter;
    9. import java.io.FileInputStream;
    10. import java.io.FileNotFoundException;
    11. import java.io.FileOutputStream;
    12. import java.io.IOException;
    13. import java.io.InputStreamReader;
    14. import java.io.OutputStreamWriter;
    15. /**
    16. * 〈一句话功能简述〉
    17. * 〈〉
    18. *
    19. * @author aaa
    20. * @create 2022/9/16
    21. * @since 1.0.0
    22. */
    23. public class FileUtil {
    24. /**
    25. * @author soil
    26. */
    27. public static void main(String[] args) {
    28. // selectRtJar();
    29. getReplaceAllClass();
    30. }
    31. public static void getReplaceAllClass(){
    32. String sourse = "E:\\test/dytest/class_rt.txt";
    33. String outAddress = "E:\\test/dytest/class_demo2.txt";
    34. try {
    35. int count_L = 0;
    36. int loopCount = 0;
    37. // 源文件位置,打开它
    38. FileInputStream fin = new FileInputStream(sourse);
    39. InputStreamReader isr = new InputStreamReader(fin);
    40. BufferedReader br = new BufferedReader(isr);
    41. // 输出文件位置
    42. FileOutputStream fout = new FileOutputStream(outAddress);
    43. OutputStreamWriter osw = new OutputStreamWriter(fout);
    44. BufferedWriter bw = new BufferedWriter(osw);
    45. // 读一行
    46. String sp = br.readLine();
    47. // 只要没有读到文件尾就一直执行
    48. while (sp != null) {
    49. // 只读取以"[L"为开头的行
    50. if (sp.substring(0, 2).equals("[L")) {
    51. // 以空格来分隔这个行,返回的字符串数组中的第二个就是我们需要的信息
    52. String s = sp.split(" ")[1];
    53. StringBuilder bs = new StringBuilder(s);
    54. // 只是个测试输出,可以不加
    55. System.out.println(bs);
    56. // 循环遍历这个字符串,修改它,使它变成我们需要的格式
    57. for (int i = 0; i < bs.length(); i++) {
    58. char ch = bs.charAt(i);
    59. // 简化循环,因为我们得到的信息很有规律。只要出现大写的字母,就说明已经到了不需要执行的时候了。
    60. if (ch >= 65 && ch < 91)
    61. break;
    62. // 把'.'替换成'/',当然,代码中是因为方法的参数要求。
    63. if (ch == '.') {
    64. bs.replace(i, i + 1, "/");
    65. }
    66. // 这个是循环的执行此时。
    67. loopCount++;
    68. }
    69. // 这里在输出你的文件信息。加工后用于后续操作。
    70. bw.write(bs.toString() + '\n');
    71. // 程序需要的类文件数目。
    72. count_L++;
    73. }
    74. // 读行
    75. sp = br.readLine();
    76. }
    77. // 两个测试输出
    78. System.out.println(count_L);
    79. System.out.println(loopCount);
    80. br.close();
    81. bw.close();
    82. } catch (FileNotFoundException e) {
    83. e.printStackTrace();
    84. } catch (IOException e) {
    85. e.printStackTrace();
    86. }
    87. }
    88. public static void selectRtJar(){
    89. String sourse = "E:\\test/dytest/class.txt";
    90. String outAddress = "E:\\test/dytest/class_rt.txt";
    91. FileInputStream fin = null;
    92. InputStreamReader isr= null;
    93. BufferedReader br= null;
    94. FileOutputStream fout= null;
    95. OutputStreamWriter osw= null;
    96. BufferedWriter bw= null;
    97. try{
    98. fin = new FileInputStream(sourse);
    99. isr = new InputStreamReader(fin);
    100. br = new BufferedReader(isr);
    101. // 输出文件位置
    102. fout = new FileOutputStream(outAddress);
    103. osw = new OutputStreamWriter(fout);
    104. bw = new BufferedWriter(osw);
    105. // 读一行
    106. String sp = br.readLine();
    107. // 只要没有读到文件尾就一直执行
    108. while (sp != null) {
    109. if (sp.contains("lib\\rt.jar")) {
    110. bw.write(sp + '\n');
    111. }
    112. sp = br.readLine();
    113. }
    114. }catch (Exception e){
    115. e.printStackTrace();
    116. }finally {
    117. try {
    118. if(br!=null){
    119. br.close();
    120. }
    121. if(bw!=null){
    122. bw.close();
    123. }
    124. if(osw!=null){
    125. osw.close();
    126. }
    127. if(fout!=null){
    128. fout.close();
    129. }
    130. if(isr!=null){
    131. isr.close();
    132. }
    133. if(fin!=null){
    134. fin.close();
    135. }
    136. }catch (Exception e){
    137. e.printStackTrace();
    138. }
    139. }
    140. }
    141. }

    首先使用第一个方法selectRtJar()挑选出所有使用rtjar的类。

    在用第二个方法getReplaceAllClass();将所有的类路径转化删除多余最后输出一份斜杠形式的文件夹路径。

    二、操作复制打包rt等

    进入lib目录,解压rt.jar文件。

    运行如下类方法:

    1. /**
    2. *
    3. */
    4. import java.io.BufferedReader;
    5. import java.io.File;
    6. import java.io.FileInputStream;
    7. import java.io.FileOutputStream;
    8. import java.io.IOException;
    9. import java.io.InputStreamReader;
    10. /**
    11. * @author aaa
    12. *
    13. */
    14. public class CopyClass {
    15. private String source = "E:\\test\\jre\\lib/"; // 类源目录
    16. private String dest = "E:\\test\\jre\\lib/"; // 类拷贝目的目录
    17. String[] jarArr = new String[] { "rt", "charsets" };
    18. /***
    19. *
    20. * @param source
    21. * 类源目录
    22. * @param dest
    23. * 类拷贝目的目录
    24. * @param jarArr
    25. * 需要的提取的jar文件
    26. */
    27. public CopyClass(String source, String dest, String[] jarArr) {
    28. this.source = source;
    29. this.dest = dest;
    30. this.jarArr = jarArr;
    31. }
    32. public static void main(String[] args) {
    33. String[] jarArr = new String[] { "rt"};
    34. CopyClass obj = new CopyClass("E:\\test/dytest\\jre\\lib/",
    35. "E:\\test/dytest\\jre\\lib/", jarArr);
    36. obj.readAndCopy("E:\\test/dytest/class_demo2.txt");
    37. }
    38. /***
    39. * @param logName
    40. * 提取class明细
    41. */
    42. public void readAndCopy(String logName) {
    43. int count = 0; // 用于记录成功拷贝的类数
    44. try {
    45. FileInputStream fi = new FileInputStream(logName);
    46. InputStreamReader ir = new InputStreamReader(fi);
    47. BufferedReader br = new BufferedReader(ir);
    48. String string = br.readLine();
    49. while (string != null) {
    50. if (copyClass(string) == true){
    51. count++;
    52. } else{
    53. System.out.println("ERROR " + count + ": " + string);
    54. }
    55. string = br.readLine();
    56. }
    57. br.close();
    58. } catch (IOException e) {
    59. System.out.println("ERROR: " + e);
    60. }
    61. System.out.println("count: " + count);
    62. }
    63. /**
    64. * 从原jar路径提取相应的类到目标路径,如将java/lang/CharSequence类从rt目录提取到rt1目录
    65. *
    66. * @param string
    67. * 提取类的全路径
    68. * @return
    69. * @throws IOException
    70. */
    71. public boolean copyClass(String string) throws IOException {
    72. String classDir = string.substring(0, string.lastIndexOf("/"));
    73. String className = string.substring(string.lastIndexOf("/") + 1, string.length()) + ".class";
    74. FileOutputStream fout;
    75. FileInputStream fin;
    76. boolean result = false;
    77. for (String jar : jarArr) {
    78. File srcFile = new File(source + "/" + jar + "/" + classDir + "/" + className);
    79. if (!srcFile.exists()) {
    80. continue;
    81. }
    82. byte buf[] = new byte[256];
    83. fin = new FileInputStream(srcFile);
    84. /* 目标目录不存在,创建 */
    85. File destDir = new File(dest + "/" + jar + "1/" + classDir);
    86. if (!destDir.exists())
    87. destDir.mkdirs();
    88. File destFile = new File(destDir + "/" + className);
    89. fout = new FileOutputStream(destFile);
    90. int len = 0;
    91. while ((len = fin.read(buf)) != -1) {
    92. fout.write(buf, 0, len);
    93. }
    94. fout.flush();
    95. result = true;
    96. break;
    97. }
    98. return result;
    99. }
    100. }

    改路径为自己的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也替换掉!

  • 相关阅读:
    机器学习笔记 - 图解对象检测任务(1)
    SpringBoot的error用全局异常去处理
    (2022牛客多校五)G-KFC Crazy Thursday(二分+哈希)
    OpenCV每日函数 结构分析和形状描述符(9) ApproxPolyDP函数 拟合曲线
    如何手动运行一个容器【一】
    【C++】obj模型文件解析(tiny_obj_loader)
    安卓中轻量级数据存储方案分析探讨
    武汉凯迪正大KDHG-220P互感器综合测试仪
    黑盒测试的5种方法介绍
    Vue3 ElementPlus el-cascader级联选择器动态加载数据
  • 原文地址:https://blog.csdn.net/qq_38423798/article/details/126951319