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

相关文章
相关标签/搜索