• 整理JRE瘦身或精简JRE


    http://blog.csdn.net/xiaoping8411/article/details/6973887

    前不久给朋友做了一个桌面程序,程序文件没多大,但运行java程序需要jre,但jre足足有80M多,然后在网上搜了如何给给JRE瘦身或精简JRE,整理如下:

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

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

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

    一、bin瘦身主要从两方面考虑

    ① exe文件,最主要的工具是java.exe,它用来执行class文件,如果只是为了单纯运行Java程序的话,其他可执行文件一般都是用不到的(可剔除). 

    ② DLL文件,是java.exe执行class文件过程中调用的,执行class文件,java.exe需要哪个库文件就加载哪个dll,不需用的可以剔除.

    我们要做的就是找到哪些DLL文件是有用?我们运行一个Java文件看看,可以利用360安全卫士得到

    1、准备java文件:

    [html] view plain copy
     
    1. /*  
    2. @author jarg  
    3. @TODO 举例查看当前程序必需的dll文件  
    4. */  
    5. import java.io.InputStreamReader;  
    6. import java.io.IOException;  
    7.   
    8. public class Hello  
    9. {  
    10.     public static void main(String[] args) throws IOException  
    11.     {  
    12.         InputStreamReader ir = new InputStreamReader(System.in);  
    13.         System.out.println("Hello");  
    14.         ir.read();  
    15.     }  
    16. }  
    2、编译、运行

    3、360安全卫士 -> 功能大全 -> 进程管理器 右上角的显示加载到当前选中进程中的dll

    4、这样我们留下java.exe、有用的dll文件和client目录就行

    到这里bin的瘦身成功!

    二、lib的瘦身

    ① lib目录最主要的类库是rt.jar,是任意Java程序所必需的类库.
    lib目录大约62MB,但是rt.jar类库就占了47MB,可见精简bin目录,最主要是裁剪rt.jar.

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

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

    主要步骤如下:

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

    [plain] view plain copy
     
    1. @echo off  
    2. C:/Java/jdk1.6.0_16/bin/java -jar  -classpath lib/*.jar; -verbose:class printSoft.jar >> class.txt  
    3. pause  
    在class.txt文件中保存如下的信息:
    [plain] view plain copy
     
    1. [Loaded java.lang.Math from shared objects file]  
    2. [Loaded java.nio.charset.Charset$3 from C:Javajdk1.6.0_16jrelib t.jar]  
    3. [Opened C:Javajdk1.6.0_16jrelibcharsets.jar]  
    4. [Loaded sun.nio.cs.AbstractCharsetProvider from C:Javajdk1.6.0_16jrelib t.jar]  
    5. [Loaded sun.nio.cs.ext.ExtendedCharsets from C:Javajdk1.6.0_16jrelibcharsets.jar]  
    6. [Loaded java.lang.Class$1 from shared objects file]  
    7. [Loaded sun.reflect.ReflectionFactory$1 from shared objects file]  
    8. [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就剩下如下信息:

    [plain] view plain copy
     
    1. java/lang/Object  
    2. java/io/Serializable  
    3. java/lang/Comparable  
    4. java/lang/CharSequence  
    5. java/lang/String  
    6. java/lang/reflect/GenericDeclaration  
    7. .......  
    2、从现有的jar包中提取我们整理的class文件,然后打包成jar,最终取代原有的jar,下面是一个提取class的工具类:
    [java] view plain copy
     
    1. import java.io.BufferedReader;  
    2. import java.io.File;  
    3. import java.io.FileInputStream;  
    4. import java.io.FileOutputStream;  
    5. import java.io.IOException;  
    6. import java.io.InputStreamReader;  
    7.   
    8. public class CopyClass  
    9. {  
    10.     private String source = "C:\Users\lzp\Desktop\printSoft\jre6\lib\";      // 类源目录  
    11.     private String dest = "C:\Users\lzp\Desktop\printSoft\jre6\lib\";        // 类拷贝目的目录  
    12.     String[] jarArr = new String[]{"rt","charsets"};  
    13.     /*** 
    14.      *  
    15.      * @param source 类源目录 
    16.      * @param dest   类拷贝目的目录 
    17.      * @param jarArr 需要的提取的jar文件 
    18.      */  
    19.     public CopyClass(String source,String dest,String[] jarArr){  
    20.         this.source=source;  
    21.         this.dest=dest;  
    22.         this.jarArr=jarArr;  
    23.     }  
    24.   
    25.     public static void main(String[] args)  
    26.     {  
    27.         String[] jarArr = new String[]{"rt","charsets"};  
    28.         CopyClass obj = new CopyClass("C:\Users\lzp\Desktop\printSoft\jre6\lib\",  
    [java] view plain copy
     
    1.                                                          "C:\Users\lzp\Desktop\printSoft\jre6\lib\",jarArr);  
    2.         obj.readAndCopy("C:\Users\lzp\Desktop\printSoft\class.txt");  
    3.     }  
    4.   
    5.     /*** 
    6.      * @param logName 提取class明细 
    7.      */  
    8.     public void readAndCopy(String logName)  
    9.     {  
    10.         int count = 0;  // 用于记录成功拷贝的类数  
    11.         try  
    12.         {  
    13.             FileInputStream fi = new FileInputStream(logName);  
    14.             InputStreamReader ir = new InputStreamReader(fi);  
    15.             BufferedReader br = new BufferedReader(ir);  
    16.   
    17.             String string = br.readLine();  
    18.             while(string != null)  
    19.             {  
    20.                 if(copyClass(string) == true)  
    21.                     count++;  
    22.                 else  
    23.                     System.out.println("ERROR " + count + ": " + string);  
    24.                 string = br.readLine();  
    25.             }  
    26.         }  
    27.         catch (IOException e)  
    28.         {  
    29.             System.out.println("ERROR: " + e);  
    30.         }  
    31.         System.out.println("count: " + count);  
    32.     }  
    33.   
    34.     /*** 
    35.      * 从原jar路径提取相应的类到目标路径,如将java/lang/CharSequence类从rt目录提取到rt1目录 
    36.      * @param string 提取类的全路径 
    37.      * @return 
    38.      * @throws IOException 
    39.      */  
    40.     public boolean copyClass(String string) throws IOException  
    41.     {  
    42.         String classDir = string.substring(0,string.lastIndexOf("/"));  
    43.         String className = string.substring(string.lastIndexOf("/")+1,string.length()) + ".class";  
    44.           
    45.         boolean result =false;  
    46.           
    47.         for(String jar : jarArr){  
    48.             File srcFile = new File(source + "/"+jar+"/" + classDir + "/" + className);  
    49.             if(!srcFile.exists())  
    50.             {  
    51.                 continue;  
    52.             }  
    53.               
    54.             byte buf[] = new byte[256];  
    55.             FileInputStream fin = new FileInputStream(srcFile);  
    56.   
    57.             /* 目标目录不存在,创建 */  
    58.             File destDir = new File(dest + "/"+jar+"1/" + classDir);  
    59.             if(!destDir.exists())  
    60.                 destDir.mkdirs();  
    61.   
    62.             File destFile = new File(destDir + "/" + className);  
    63.             FileOutputStream fout = new FileOutputStream(destFile);  
    64.             int len = 0;  
    65.             while((len = fin.read(buf)) != -1)  
    66.             {  
    67.                 fout.write(buf,0,len);  
    68.             }  
    69.             fout.flush();  
    70.             result = true;  
    71.             break;  
    72.         }  
    73.         return result;  
    74.     }  
    75. }  
    然后在将提取的class文件打包成jar文件,利用jar命令进行打包,然后替换以前的jar文件,这样lib就从以前的六十多M到几M多有,如图:

    这样我们就完成了jre的瘦身!

  • 相关阅读:
    UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)
    UVA 1393 Highways,UVA 12075 Counting Triangles —— (组合数,dp)
    【Same Tree】cpp
    【Recover Binary Search Tree】cpp
    【Binary Tree Zigzag Level Order Traversal】cpp
    【Binary Tree Level Order Traversal II 】cpp
    【Binary Tree Level Order Traversal】cpp
    【Binary Tree Post order Traversal】cpp
    【Binary Tree Inorder Traversal】cpp
    【Binary Tree Preorder Traversal】cpp
  • 原文地址:https://www.cnblogs.com/donaldlee2008/p/5832025.html
Copyright © 2020-2023  润新知