java jre精簡瘦身(轉載學習)

打開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的瘦身!

相關文章
相關標籤/搜索