精簡jre(JDK6瘦身)

參考文章:

http://glemir.xplore.cn/archives/200

http://blog.csdn.net/nsrainbow/archive/2008/04/26/2333206.aspx

 

這裏結合參考的文章和網上的一些JRE瘦身經驗說下我精簡JRE的過程。

 

精簡過的JRE一般都不是通用的,都是針對自己的應用程序把不需要的類去掉,從而達到精簡目的。所以有些人想拿別人精簡過的JRE運行自己的應用程序,這樣是不靠譜的。最後還是得自己動手精簡,過程也挺簡單。

 

思路:

把自己的應用程序打包成jar,然後通過jar命令運行這個jar,把jar所需的類全部打印到一個文本文件裏面,把文本文件裏面的類提取出來,重新打包。覆蓋JRE目錄中的JAR包。去掉JRE下bin目錄和lib目錄中不需要得。瘦身完成。

 

應用程序打包後是test.jar,jre(目錄) 也和它同一文件夾,寫一個CMD腳本方便測試:

@echo off
set path=./jre6/bin
java -jar -verbose:class test.jar >>class.txt
pause

 

這樣程序使用的就是當前目錄下的jre,程序運行後,最好把所有的功能使用一遍,這樣輸出了一個文件class.txt,裏面有所有需要的class,其格式如下:

[Opened D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.Object from D:\data\dict\jre\lib\rt.jar]
[Loaded java.io.Serializable from D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.Comparable from D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.CharSequence from D:\data\dict\jre\lib\rt.jar]
[Loaded org.apache.lucene.index.CompoundFileReader$FileEntry from file:/D:/data/dict/dict.jar]

輸出的class文件裏面可能還包含其他應用的jar包,如:charsets.jar。這樣就需要把class文件裏面的信息按rt和charsets分成兩類分別放到兩個txt文件裏面:rt_class.txt,charsets.txt

我們依照這個文件來裁剪rt.jar:
首先在utralEdit中進行一些處理,去掉所有不是rt.jar中的class的行,去掉from後面的,去掉loaded等無關項目,再把“.”替換成“/”.這個可以利用正則表達式等輕鬆處理。處理完後得到的文件類似如下格式:

 rt_class.txt

java/lang/Object
java/io/Serializable
java/lang/Comparable
java/lang/CharSequence
java/lang/String 

 

我們依照這個文件來裁剪charsets.jar:
首先在utralEdit中進行一些處理,去掉所有不是charsets.jar中的class的行,去掉from後面的,去掉loaded等無關項目,再把“.”替換成“/”.這個可以利用正則表達式等輕鬆處理。處理完後得到的文件類似如下格式:

charsets.txt

sun/nio/cs/ext/ExtendedCharsets 
sun/nio/cs/ext/GBK 
sun/nio/cs/ext/DoubleByteDecoder 
sun/nio/cs/ext/GBK$Decoder 
sun/nio/cs/ext/DoubleByteEncoder 
sun/nio/cs/ext/GBK$Encoder 

 然後寫一個腳本或者程序處理,從rt或charsets中把需要的的class拷貝到另一個對應的文件夾rt1或charsets1,這裏參考網上的一個JAVA抽取程序。

 

在運行下面JAVA程序之前需要將JRE目錄中rt.jar,charsets.jar分別解壓到相應目錄

 

代碼如下:

package com.ccic.greenjvm;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;

public class ReduceRt {
	// 文件拷貝
	public static boolean copy(String file1, String file2) {
		try // must try and catch,otherwide will compile error
		{
			// instance the File as file_in and file_out
			java.io.File file_in = new java.io.File(file1);
			java.io.File file_out = new java.io.File(file2);
			FileInputStream in1 = new FileInputStream(file_in);
			FileOutputStream out1 = new FileOutputStream(file_out);
			byte[] bytes = new byte[1024];
			int c;
			while ((c = in1.read(bytes)) != -1)
				out1.write(bytes, 0, c);
			in1.close();
			out1.close();
			return (true); // if success then return true
		} catch (Exception e) {
			System.out.println("Error!");
			return (false); // if fail then return false
		}
	}

	// 讀取路徑,copy
	public static int dealClass(String needfile, String sdir, String odir) throws IOException {
		int sn = 0; // 成功個數

		File usedclass = new File(needfile);
		if (usedclass.canRead()) {
			String line = null;
			LineNumberReader reader = new LineNumberReader(new InputStreamReader(new FileInputStream(usedclass),
					"UTF-8"));
			while ((line = reader.readLine()) != null) {
				line = line.trim();
				int dirpos = line.lastIndexOf("/");
				if (dirpos > 0) {
					String dir = odir + line.substring(0, dirpos);
					File fdir = new File(dir);
					if (!fdir.exists())
						fdir.mkdirs();
					String sf = sdir + line + ".class";
					String of = odir + line + ".class";
					boolean copy_ok = copy(sf.trim(), of.trim());
					if (copy_ok)
						sn++;
					else {
						System.out.println(line);
					}

				}

			}
		}
		return sn;

	}

	public static void main(String[] args) {
		String needfile = "D:/greanjvm/rt_class.txt";//運行JAR生成的,應用程序所需類的txt文件
		String sdir = "D:/greanjvm/rt/"; //rt.jar解壓後的目錄
		String odir = "D:/greanjvm/rt1/";//抽取的類存放目錄
		try {
			int sn = dealClass(needfile, sdir, odir);
			System.out.print(sn);
		} catch (IOException e) {
			e.printStackTrace();
		}

	}
}

 

所需的類都抽取到rt1目錄之後,把原rt目錄中的“META-INF”文件夾拷貝到rt1下面,進入rt1目錄,用rar壓縮工具打包成rt.zip,改名爲rt.jar,然後替換jre6/lib目錄下的rt.jar。

 

charsets1目錄處理同上。

 

所需類的精簡工作已經完成,接下來精簡其他的。

 

1、Jre目錄下的license都刪除,只留bin和lib目錄

2、bin下的執行文件需要運行jar時用DLL_Killer工具查看使用到了哪些文件

3、lib下只要保留 rt,charsets庫就可以了(因爲應用程序只用到了這兩個)。

4、除了i386和zi兩個子目錄外,其餘的子目錄都可以不要(原則上都要自己試試看刪除其他目錄會不會報錯)。

5、Zi下只需要保留自己地區的子目錄和其下的一些文件就可以(這裏Zi下我只保留了America文件夾)。

6、Lib下除了庫之外的屬性文件都要保留。

 

優化完成!!!!!!!!!!!

 

 

注意事項:

1、精簡BIN目錄
  *運行JAR包時需指定PATH路徑,不然會默認搜索環境變量中的JDK路徑。
  *用DLL_Killer工具查看任務管理器中java.exe調用的DLL庫

2、精簡LIB目錄
  *抽取出的類重新打包成rt.jar時要注意,用JAR命令和rar工具打的jar包都不行。解決如下:
 -將原生的rt.jar用rar打開,然後進入相關目錄,刪除掉相關目錄或者文件,再把抽取出來的類拖進來就行了。
  *zi文件夾下只留America文件夾

 

BIN目錄

 

 

lib目錄

 

JVM目錄

 

 

哥的整個測試目錄

 

 

精簡後JRE接近7M

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章