`
Stream.Town
  • 浏览: 23493 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

JRE精简攻略

    博客分类:
  • Java
 
阅读更多

       前言

       前段时间用Java完成了一个本地工具的开发,但在推广时发现让用户自己去安装JDK是件很麻烦的事情,而且JDK版本的不统一也给工具的正常运行带来很多影响,于是自己就准备将JRE精简后打包到程序中。

   

      JRE精简的网上教程有很多,像GreenJVM一类的工具也有很多,但这些教程和工具在自己的一番试用之下没一个管用的,所以只好自己动手,丰衣足食。

    

      工具准备:process explorer(附件中有下载)

   

      步骤一 选择要精简的JRE版本

      选择好目标才好动手,首先要根据自己程序的需要选择好对应的JRE版本,1.6,1.7等等,更重要的是选好32位还是64位。此处建议选择32位的JRE,因为32位的JRE是可以运行在64位操作系统上的,而64位的是不能运行在32位操作系统上的。

    

      步骤二 精简DLL文件
 
     启动自己所写的JAVA应用,打开process explorer,在进程列表中选中java(或javaw),按下ctrl+d,就可以在下方面板中查看到java.exe运行时所调用dll文件及其所在路径,将jre\bin\路径下除这些文件之外的dll全部删除,即可完成dll文件的精简了。

     

     步骤三 精简jar和ttf
      
AVA应用的运行,打开process explorer,在进程列表中选中java(或javaw),按下ctrl+h,就可以在下方面板中查看到程序运行时所使用的jar和ttf文件,在jre\lib\下移除掉其他无用的jar和ttf即可。



   

      步骤四 精简其他资源
      现在lib文件夹下应该只剩下一些配置文件和图标等文件,建议保留\lib\下面.properties,xlist,.data等文件,保留zi目录下面用到的国家配置文件,其他的按使用情况删除即可。

       bin目录下面的exe除了java或javaw其他的也都可以删掉,只要在process explorer中没有看到即可。

       最后,如果不确定的文件就先删掉以后运行一下程序试试。

      

      步骤五 精简rt.jar

      终于来到最重要也是最麻烦的一步,rt.jar的精简。一个rt.jar的体积有50多M,占到JRE总体积的三分之一还多,而其中我们用到的只有一点点,所以精简rt.jar是整个jre精简工作的核心步骤。

      首先,用如下命令运行我们的程序,具体参数请根据实际情况修改,重点在于利用-verbos:class打印出程序运行时所用到的类:

java -jar  -classpath lib/*.jar; -verbose:class myAPP.jar >> classes.txt 

      启动后将程序的所用功能都运行一遍,一定把每个功能都过一遍才可以,尤其是tooltip等容易被忽略的要特别注意。全部运行完后,会生成一份如下的classes.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]

    接着,将jre下的rt.jar解压到一个rt文件夹中,利用如下的RTCutter程序,将rt文件夹所在的目录和class.txt的路径作为输入,即可得到一份精简好的rt1文件夹了:

     

package com.tc.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class RTCutter {
	private String source = null; // 类源目录
	private String dest = null; // 类拷贝目的目录
	String[] jarArr = new String[] {"rt" };

	/***
	 * 
	 * @param source
	 *            类源目录
	 * @param dest
	 *            类拷贝目的目录
	 * @param jarArr
	 *            需要的提取的jar文件
	 */
	public RTCutter(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" };
		RTCutter obj = new RTCutter(
				"C:/JREMaker/tmp1/",
				"C:/JREMaker/tmp1/", jarArr);
		obj.cutRT("D:/classes.txt");
	}

	/***
	 * 根据classes.txt文件精简rt目录
	 * @param logName
	 *            提取class明细
	 */
	public void cutRT(String logName) {
		List<String> cList = getClassesListFromFile(logName);
		int count = 0; // 用于记录成功拷贝的类数
		try {
			for(String klass : cList) {
				if (copyClass(klass)) {
					count++;
				} else {
					System.out.println("ERROR " + count + ": " + klass);
				}
			}
		} 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 {
		if (string.lastIndexOf("/") == -1) {
			return false;
		}
		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;
			fin.close();
			fout.close();
			break;
		}
		return result;
	}
	
	/**
	 * 将原始的classes.txt转换为类名列表
	 * @param source 由-verbose:classes选项生成的classes.txt的路径
	 */
	private List<String> getClassesListFromFile(String source) {
		BufferedReader reader = null;
		ArrayList<String> classList = new ArrayList<>();
		try {
			reader = new BufferedReader(new FileReader(source));
			String line = null;
			while((line = reader.readLine()) != null) {
				if (line.startsWith("[")) {
					if (line.startsWith("[Opened")) {
						continue;
					}
					line = line.replace("[Loaded ", "");
					int index = line.indexOf("from");
					if (index >= 0) {
						line = line.substring(0, index);
					}
					line = line.trim().replace(".", "/");
					classList.add(line);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				reader.close();
			} catch (Exception e) {
				
			}
		}
		return classList;
	}
}

     

     RTCutter程序处理后,会在rt所在目录下面生成一个rt1目录,里面就是精简后的之后的rt了,利用jar命令将rt1目录里的类打包成新的rt.jar:

     

jar cf rt.jar com java javax org sun

 

    这样rt.jar的精简就完成了,当然还需要用新的rt.jar运行一下程序,如果出现了classNotFound的异常,就需要把缺少的类放到rt1目录中,再重新打包。

 

    若程序之后的版本做了改动,那么仍需要利用-verbose:classes参数来运行程序,将改动的功能单独运行一次,利用RTCutter得到一个rt1目录,并和之前的rt1目录合并一下,再打包生成一个新的rt.jar。当然,如果更牛一点,这些步骤都可以在ant脚本中实现。

 

    结语

    整个JRE的精简就是上面的5步了,整体过程还是比较简单的,就是在精简中肯定会需要大量的时间去验证,而且在后续的版本升级和维护方面也会有很多工作,另外利用精简化的jre也有可能出现一些莫名其妙的问题,同时也使得程序失去了跨平台的兼容性,这些因素都是需要在确立精简方案之前需要考虑的,用户的易用性和程序的可维护性中间终究要找到一个平衡。

 

 

 

  • 大小: 482.4 KB
  • 大小: 412.5 KB
分享到:
评论

相关推荐

    jre精简工具(附详细教程).

    首先,我们需要理解JRE精简的目的:减少不必要的库和模块,只保留运行特定Java应用程序所需的最小集。这样可以降低存储需求,提高启动速度,并减小安全风险,因为精简后的JRE不包含未使用的代码。 精简JRE通常涉及...

    JRE瘦身 jre减肥 精简jre jre精简

    因为很多用户的电脑上没有合适版本的jre。用一个软件的同时必须安装另外一个软件(jre)会给人一种流氓软件强行捆绑的感觉,而很多用户对此很抵触。更不要提用户电脑上的jre版本千变万化(有没有jre,是微软的还是...

    JRE精简工具(超级好用,含使用说明)

    "JRE精简工具"就是为了解决这个问题而设计的,它可以帮助开发者定制化自己的JRE,去除不必要的部分,只保留运行特定应用所需的最小功能集。 这个工具包包含以下文件: 1. `make.bat`:这是一个批处理脚本,通常...

    精简版jre1.8(wins 64位,附压缩教程)

    最近在写一个java开发的游戏,jre1.8.0_181整整有199mb,对于一个只有400多k的游戏来说,完全没必要,于是就进行精简,把jre精简到22.5mb,游戏也能正常运行。如果你急需使用精简的jre,可以下载试试。本来想精简到...

    精简的jre的精简工具

    GreenJVMMake - CSDN下载 下载 这是一个配合GreenJVM使用的JRE精简工具,可以动态的获取应用程序中对于rt.jar的class依赖,并根据依赖关系自动构成精简后的rt.jar.

    精简的jre和精简过程

    最近在写一个小程序,jre1.8.0_181整整有199mb,对于一个只有400多k的程序来说,完全没必要,于是就进行精简,把jre精简到40M、左右,程序也能正常运行。如果你急需使用精简的jre,可以下载试试。

    自己项目的jre精简版

    本项目提供的“自己项目的jre精简版”是一个经过定制优化的JRE版本,特别针对非Web应用,主要适用于依赖AWT(Abstract Window Toolkit)图形界面的应用程序。 JRE精简版通常是为了减少不必要的文件和功能,以降低...

    精简 jre 效果程序

    "精简 jre 效果程序"这个主题指的是对标准的JRE进行优化和裁剪,以减少其体积,提高运行效率或适应特定的系统需求。 1. **JRE组成部分**: JRE主要由以下几个部分组成: - Java虚拟机(JVM):负责解释并执行Java...

    Jre8精简基础镜像包

    制作 docker 精简 jre8 基础镜像,基础镜像为bitnami/minideb,jdk8u321版本,已解决httpclient中文乱码和webservice-client缺包问题。

    精简jre步骤 迷你jre制作过程

    精简jre步骤 1. 拷贝一个完整版的jre文件夹到D盘 2. 删除jre目录下所有出bin和lib目录的所有文件或目录 3. 打开cmd窗口,设置path路径为空,转到D:\jre\bin目录,运行java –version。正常显示当前Java的版本。 4. ...

    jre精简工具(附详细教程)

    本文将详细介绍如何使用一款JRE精简工具来定制自己的JRE安装包,以满足特定项目需求并优化资源占用。 一、为何需要精简JRE 1. 减少体积:标准JRE包含了许多不必要的组件,对于特定应用可能只需要部分功能,精简后...

    精简版jre.zip 64位 1.8.0压缩后才20M

    适合需要通过java开发桌面程序的小朋友

    jre精简工具BantingJRE+setup安装程序

    为了解决这个问题,"jre精简工具BantingJRE+setup安装程序"应运而生。 BantingJRE是一个专门针对JRE进行定制和精简的工具,它的主要目标是根据用户的具体需求,仅保留运行特定Java程序所需的组件,从而减小JRE的...

    JRE精简版java虚拟机

    JRE精简版则是针对特定需求优化过的版本,通常是为了减少体积、提高运行效率或简化安装过程。 Java虚拟机是Java平台的核心部分,它的主要职责是解释和执行Java字节码。JVM使得Java具有了“一次编写,到处运行”的跨...

    jre8 官方精简的 compat

    在本文中,我们将深入探讨"jre8 官方精简的 compat"这一主题,了解其背后的含义、精简程度以及与Java运行环境的关系。 标题中的"jre8 官方精简的 compat"指的是Java Runtime Environment 8的一个特别版本,它经过了...

    精简版JRE.rar

    本压缩包"精简版JRE.rar"提供了一个经过优化的JRE版本,旨在满足开发者在特定场景下对轻量级、快速部署的需求。 首先,我们来详细了解JRE的组成部分及其作用: 1. **Java虚拟机(JVM)**:JVM是Java平台的核心,它...

    jre精简镜像体积120M左右

    jre精简镜像体积120M左右,基于alpine仅适用于jre环境。

    超级精简版的jre

    标题中的"超级精简版的jre"指的是对标准JRE进行优化和裁剪,移除了不必要的组件和服务,以实现更小的体积、更快的启动速度以及更低的资源消耗。 精简版JRE通常是为了满足特定应用场景的需求,比如嵌入式设备、低...

    jsmooth0.9.9-7汉化版+jre精简版

    JRE精简版是针对特定应用优化过的Java运行环境,它只包含了运行该应用程序所需的最小组件,从而降低了文件大小和运行时的系统资源占用。这使得转化后的.exe文件更轻巧,下载和运行速度更快,同时减少了对用户计算机...

Global site tag (gtag.js) - Google Analytics