博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java jre精简瘦身(转载学习)
阅读量:5903 次
发布时间:2019-06-19

本文共 5107 字,大约阅读时间需要 17 分钟。

hot3.png

打开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文件:

/*@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();	}}

2、编译、运行

3、360安全卫士 -> 功能大全 -> 进程管理器 右上角的显示加载到当前选中进程中的dll(也可以用其它工具或者直接用tasklist命令导出)

90f94be73926c53dbd77402c150741f6630.jpg

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

9ffd92f24059ec7b7eaef62f4c3fcc423da.jpg

到这里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程序时所加载的所有类,如:

@echo offC:/Java/jdk1.6.0_16/bin/java -jar  -classpath lib/*.jar; -verbose:class printSoft.jar >> class.txtpause

在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/Objectjava/io/Serializablejava/lang/Comparablejava/lang/CharSequencejava/lang/Stringjava/lang/reflect/GenericDeclaration.......

2、从现有的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多有,如图:

00a7d23f08a5abac0f784c0648e3587e168.jpg

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

转载于:https://my.oschina.net/haitaohu/blog/2243410

你可能感兴趣的文章
微软面试题: 找出二叉树上任意两个结点的最近共同父结点。
查看>>
机器学习 - pycharm, tensorflow集成篇
查看>>
Springboot 之 引入Thymeleaf
查看>>
Java基础-位运算符Bitwise Operators
查看>>
Linux常用基本命令( rmdir, rm, mv )
查看>>
python 排列组合
查看>>
python 取整的两种方法
查看>>
POJ2406 Power Strings(KMP)
查看>>
java B2B2C Springcloud电子商城系统-Feign基本使用
查看>>
Qtum量子链x2018区块链新经济论坛:区块链基础设施建设发展方向
查看>>
Java反射与hook混用反射某支付的方法
查看>>
前端性能优化 - Resource Hints 资源预加载
查看>>
JavaScript-console的使用_016
查看>>
两种方式设置iframe的高度区别
查看>>
应用后台省电秘籍——低功耗状态下应用如何正常运行?
查看>>
Iterator 和 for...of 循环
查看>>
PAT A1086
查看>>
浮动的label
查看>>
前端工程化
查看>>
关于iOS 11.x微信连wifi流程中,在Portal页无法拉起微信问题的简单记录
查看>>