精简JRE的思路初探
引言: JRE是Java程序赖以执行的基础环境,眼下JRE已经很的庞大;即使为了执行一个简单的Hello World的程序。可能依旧须要依赖整个JRE,将近百兆大小的依赖性。
能否够对特定Java程序依赖的JRE进行精简呢? 当然是能够。依据当前代码的须要,动态精简JRE,仅仅依赖须要的class。而非所有。
1. 总体的思路
a. 首先找到当前Java程序依赖的全部class,包含自身类库/第三方类库,以及JRE中的类库。
b. 将JRE中不须要的类库文件移除掉,仅仅保留须要的类库。
C. 将保留下的类库又一次打包。替换已有的JRE文件
2. 寻找所需的JRE中的类库文件
在执行Java应用的过程中,能够针对JVM加入參数[-XX:+TraceClassLoading],则应用在启动过程中,会将全部的所需的class打印到控制台。
在上述的样例中,就列出全部依赖的类库。
2. 怎样提取须要的类库或者移除不须要的类库
这里我们採用前者,仅仅提取所需的类库。
jar xvf xxx.jar classname1 classname2 ....
这个命令就会把须要的class从jar中提取出来,拷贝到本地当前文件夹。
3. 将这些类库进行打包,替换掉JRE中相应的类库
jar cvf target.jar sourcefolder1 classfolder2 ...
打包命令,将classfolder中的类库,打包为target.jar.
4. 那代码上怎样。利用上述的仅仅是完毕自己主动化打包 JRE相应的类库呢?
方案例如以下:
4.1. 基于执行过程中的Java參数-XX:+TraceClassLoading,打印出所用在JRE中用到的java类
4.2. 捕获从控制台输出的class列表
4.3. 利用jar自带的功能。从rt.jar中提取对应的所须要的class
4.4. 将rt.jar中提取的class进行打包,就可以得到所需的jre核心jar包。
代码假定的前提:
1. Jre所在的路径
2. 目标java类已经编译成class.这里未考虑动态编译的情况
3. 将jre中的rt.jar打包在当前路径。
演示样例代码例如以下:
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List; public class RunClass { public static void main(String[] args) throws IOException {
List<String> classes = new ArrayList<String>(); String[] cmdB = { "java", "-XX:+TraceClassLoading", "MainTest" };
Runtime runtime = Runtime.getRuntime(); Process process = Runtime.getRuntime().exec(cmdB);
// /process = Runtime.getRuntime().exec(cmdB);
LineNumberReader br = new LineNumberReader(new InputStreamReader(
process.getInputStream()));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
String className = RunClass.parseClass(line);
if (className.length() > 0) { sb.append(className.replace(".", "/")).append(" ");
classes.add(className.replace(".", "/"));
}
} System.out.println("classes to be packed in size:" + classes.size()); classes.add(0, "/opt/jdk7/jre/lib/rt.jar");
classes.add(0, "xvf");
classes.add(0, "jar"); Process jarClass = runtime.exec((String[]) classes
.toArray(new String[classes.size()]));
LineNumberReader br1 = new LineNumberReader(new InputStreamReader(
jarClass.getInputStream()));
StringBuffer sb1 = new StringBuffer();
String line1;
while ((line1 = br.readLine()) != null) {
System.out.println("extracting:" + line1);
}
System.out.println(classes.size()
+ " classes have been extracted successfully"); String[] cmdJarPackage = { "jar", "cvf", "rt.jar", "com", "java",
"javax", "META-INF", "org", "sun", "sunw" };
Process jarProcess = runtime.exec(cmdJarPackage); System.out
.println("Jar the classes into a package rt.jar successfully."); } public static String parseClass(String lineStr) {
String keyStr = ""; if (lineStr.startsWith("[Loaded")) {
String[] keys = lineStr.split(" "); if (keys.length == 4) {
keyStr = keys[1];
}
} return keyStr;
} }
5. 总结
JRE在jDK8中已经对其进行了模块化设计,从而使按需载入和定制JRE成为可能。这里的演示样例代码仅仅是简单示意了流程,离真正的工具化还有较大差距;基本的原因是大量使用了Runtime.exec方法来直接调用命令,这样不是非常灵活和可控;比方打包和解压能够利用JarOuputStream, JarInputStream等来进行等。会更加可控和灵活。
精简JRE的思路初探的更多相关文章
- Java 精简Jre jar打包成exe
#开始 最近几天都在忙一个事情,那就是尝试精简jre,我想不明白为什么甲骨文官方不出exe打包工具... 网络上精简jre的文章很多,但是原创的似乎没几个,绝大多数都是转发同一个博客, 这里借鉴了不少 ...
- 整理JRE瘦身或精简JRE
http://blog.csdn.net/xiaoping8411/article/details/6973887 版权声明:本文为博主原创文章,未经博主允许不得转载. 前不久给朋友做了一个桌面程序, ...
- PAT 1020 月饼 (25)(精简版代码+思路+推荐测试用例)
1020 月饼 (25)(25 分)提问 月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼.现给定所有种类月饼的库存量.总售价.以及市场的最大需求量,请你计算可以获得的最大收益是 ...
- PAT 1024 科学计数法 (20)(精简版代码+思路+推荐测试样例)
1024 科学计数法 (20)(20 分) 科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式[+-][1-9]"."[0-9]+E[+-][0-9]+, ...
- Java&.Net虚拟机精简(GreenJVM&GreenDotNet发布) .
精简JRE体积的小工具:http://blog.csdn.net/cping1982/archive/2008/09/02/2865198.aspx 项目地址:http://code.google.c ...
- 玩转BLE(3)_使用微信蓝牙精简协议伪造记步数据
1. 前言 在物联网时代,有一个问题肯定会让人头疼(现在已经初露端倪了): 物联网中的IOT设备有两个主要特点: 1)简单小巧(不具备复杂的人机交互接口,需要手机等终端设备辅助完成配置.控制等功能). ...
- [LeetCode] Count Numbers with Unique Digits 计算各位不相同的数字个数
Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n. Examp ...
- Java安装程序制作
对于Java桌面应用来说,比较烦琐的就是安装部署问题,如:客户端是否安装有jre.jre版本.jre在哪里下载.如何用jre启动 Java应用等等.不要说刚接触电脑的人,就算是比较熟悉电脑,如果没有接 ...
- 使用exe4j把JAVA GUI程序打包成exe文件时遇到的问题
1.把项目打包成jar文件时,只要勾选src目录就行了,其他的比如资源文件和jar包是不能添加进去的. 2.在D盘建一个文件夹,最好与项目同名,然后把打包好的jar包放进去,其他资源文件(图片之类的) ...
随机推荐
- Java输入输出流(转载)
转自http://blog.csdn.net/hguisu/article/details/7418161 目录(?)[+] 1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作 ...
- 使用keil判断ARM的冷启动和热启动的方法
微处理器:LPC2114 编译环境:Keil MDK V4.10 思路: 常把单片机系统的复位分为冷启动和热启动.所谓冷启动,也就是一般所说的上电复位,冷启动后片内外RAM的内容是随机的,通常是0x0 ...
- C#dll版本号默认生成规则
原文:C#dll版本号默认生成规则 1.版本号自动生成方法 只需把 AssemblyInfo.cs文件中的[assembly: AssemblyVersion("1.0.0.0") ...
- 960 grid 使用
去官网下载960 grid,解压后可以看到css下面有如下文件: 960.css是一个综合性文件.我们要引入960 ,reset和text 3 个文件. 一般情况下调用: <link rel=” ...
- cdoj 秋实大哥与战争
首先,显然每个区间的最长连续子区间要么在左孩子里,要么在右孩子里,要么跨越两个孩子.于是我们可以对每个区间维护如下信息ll(left long),rl(rigth long),ml(mid long) ...
- 简单QT界面信号图形化输入输出
右键->转到槽,选择信号 就可以输入代码 右键->转到槽,选择信号 就可以输入代码 2个文本框接受输入数字,第3个文本框输出相加结果 void Dialog::on_pushButton_ ...
- OCP prepare 20140627
1. catalog start with catalog start with 是一个很好的命令. 有了这个命令后, 基本上可以不再使用catalog数据库了 . 因为可以通过这个命令将以前的备份 ...
- NULL、空指针,’\0’,0的去区别
http://blog.csdn.net/bailyzheng/article/details/7677628参考该博客 NULL是空指针常量.
- [C#参考]属性
属性和字段不同,属性是一个函数成员:它提供灵活的机制来读取.编写或计算某个私有字段的值. 可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法. 这使得可以轻松访问数据,此外还有 ...
- curl多线程类。
<?php /* * Curl 多线程类 * 使用方法: * ======================== $urls = array("http://baidu.com" ...