打開JRE安裝目錄.目錄包括bin,lib二個文件夾,因此就是將這兩個文件進行瘦身了,java
1. bin: 能夠認爲這是Java虛擬機.正則表達式
2. lib: 執行class文件時,Java虛擬機須要用到的類庫及資源文件.安全
1、bin瘦身主要從兩方面考慮jvm
① exe文件,最主要的工具是java.exe,它用來執行class文件,若是隻是爲了單純運行Java程序的話,其餘可執行文件通常都是用不到的(可剔除). 編輯器
② DLL文件,是java.exe執行class文件過程當中調用的,執行class文件,java.exe須要哪一個庫文件就加載哪一個dll,不需用的能夠剔除.ide
咱們要作的就是找到哪些DLL文件是有用?咱們運行一個Java文件看看,能夠利用360安全衛士獲得工具
一、準備java文件:字體
/* @author jarg @TODO 舉例查看當前程序必需的dll文件 */ import java.io.InputStreamReader; import java.io.IOException; public class Hello { public static void main(String[] args) throws IOException { InputStreamReader ir = new InputStreamReader(System.in); System.out.println("Hello"); ir.read(); } }
二、編譯、運行this
三、360安全衛士 -> 功能大全 -> 進程管理器 右上角的顯示加載到當前選中進程中的dll(也能夠用其它工具或者直接用tasklist命令導出)spa
四、這樣咱們留下java.exe、有用的dll文件和client目錄就行
到這裏bin的瘦身成功!
2、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的配置文件內容.
主要步驟以下:
一、提取咱們須要的類庫(jar),藉助-verbose命令,查看虛擬機在運行Java程序時所加載的全部類,如:
@echo off C:/Java/jdk1.6.0_16/bin/java -jar -classpath lib/*.jar; -verbose:class printSoft.jar >> class.txt pause
在class.txt文件中保存以下的信息:
[Loaded java.lang.Math from shared objects file] [Loaded java.nio.charset.Charset$3 from C:\Java\jdk1.6.0_16\jre\lib\rt.jar] [Opened C:\Java\jdk1.6.0_16\jre\lib\charsets.jar] [Loaded sun.nio.cs.AbstractCharsetProvider from C:\Java\jdk1.6.0_16\jre\lib\rt.jar] [Loaded sun.nio.cs.ext.ExtendedCharsets from C:\Java\jdk1.6.0_16\jre\lib\charsets.jar] [Loaded java.lang.Class$1 from shared objects file] [Loaded sun.reflect.ReflectionFactory$1 from shared objects file] [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就剩下以下信息:
java/lang/Object java/io/Serializable java/lang/Comparable java/lang/CharSequence java/lang/String java/lang/reflect/GenericDeclaration .......
二、從現有的jar包中提取咱們整理的class文件,而後打包成jar,最終取代原有的jar,下面是一個提取class的工具類:
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; public class CopyClass { private String source = "C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\lib\\"; // 類源目錄 private String dest = "C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\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","charsets"}; CopyClass obj = new CopyClass("C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\lib\\",
"C:\\Users\\lzp\\Desktop\\printSoft\\jre6\\lib\\",jarArr); obj.readAndCopy("C:\\Users\\lzp\\Desktop\\printSoft\\class.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(); } } 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"; boolean result =false; for(String jar : jarArr){ File srcFile = new File(source + "/"+jar+"/" + classDir + "/" + className); if(!srcFile.exists()) { continue; } byte buf[] = new byte[256]; FileInputStream fin = new FileInputStream(srcFile); /* 目標目錄不存在,建立 */ File destDir = new File(dest + "/"+jar+"1/" + classDir); if(!destDir.exists()) destDir.mkdirs(); File destFile = new File(destDir + "/" + className); FileOutputStream 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; } }
而後在將提取的class文件打包成jar文件,利用jar命令進行打包,而後替換之前的jar文件,這樣lib就從之前的六十多M到幾M多有,如圖:
這樣咱們就完成了jre的瘦身!