1. jre的运行时主要jar文件rt.jar都很大,这导致了用java做的桌面客户端程序很难发布绑定jre发布。这在很大程度上限制了java桌面软件 的分发。可是,jre并不是在所有的用户计算机上都有安装,即使安装了,也未必我们期望的版本。因此,对jre做精简,减少体积是有必要的。请你给出一个 方案,来说说如何给jre减肥,以方便我们的桌面程序绑定jre发布。并给出一个基本的实现。对这个实现的要求是:对于任意给定java程序A,应用你的 方案和实现,可以从一个完整的jre中,抽取这个程序A的必要部分,从而实现最小体积的发布。在本题中,要求你详述你的方案,并提交你实现的代码。
整个过程分为两步:
1. 找出程序依赖的所有class类文件,并整理出一个class依赖列表,具体步骤如下:
加入参数-XX:+TraceClassLoading, 启动桌面程序并且重定向console流到一个文件比如classdepenency.txt.
然后对程序做一个完整的回归测试,确保所有的功能点都已经用到了,目的是为了完整的加载所有的依赖。
因为有些依赖class可能是运行时期通过反射或者Class.forName()来加载的,这些类只有在代码被运行的时候classloader才会加载对应的依赖。
程序测试完毕后,用编辑工具比如notepad++对classdepenency.txt做一个简单的筛选,去掉与classloading无关的console信息。
只留如下所示的classloader加载rt.jar中类的信息。
[Loaded java.util.logging.LogManager$2 from F:Program FilesJavajdk1.7.0_51jrelibrt.jar]
[Loaded java.util.Collections$EmptyEnumeration from F:Program FilesJavajdk1.7.0_51jrelibrt.jar]
[Loaded java.util.EventObject from F:Program FilesJavajdk1.7.0_51jrelibrt.jar]
[Loaded java.beans.PropertyChangeEvent from F:Program FilesJavajdk1.7.0_51jrelibrt.jar]
[Loaded sun.util.logging.PlatformLogger from F:Program FilesJavajdk1.7.0_51jrelibrt.jar]
2. 写个小程序从JRE里面的rt.jar抽取出上一步筛选后的classdepenency.txt文件里记录的所有类.下面是程序的代码.
02 |
import java.io.BufferedReader; |
03 |
import java.io.FileInputStream; |
04 |
import java.io.FileOutputStream; |
05 |
import java.io.InputStream; |
06 |
import java.io.InputStreamReader; |
07 |
import java.util.ArrayList; |
08 |
import java.util.List; |
09 |
import java.util.jar.JarEntry; |
10 |
import java.util.jar.JarFile; |
11 |
import java.util.jar.JarInputStream; |
12 |
import java.util.jar.JarOutputStream; |
15 |
public class ReduceJRE { |
17 |
public static void main(String[] args) throws Exception { |
18 |
String mainJar = null; |
19 |
String classDenpdencyFile = null; |
20 |
if(args!=null && args.length==2) |
23 |
classDenpdencyFile = args[1]; |
26 |
mainJar = "F:Program FilesJavajre7librt.jar"; |
27 |
classDenpdencyFile = "F:Program FilesJavajre7libclassdepency.txt"; |
29 |
ListdepencyClass = new ArrayList(); |
30 |
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(classDenpdencyFile))); |
31 |
String templine = br.readLine(); |
32 |
// load all the dependency class and store them in a array list; |
33 |
while(templine!=null) { |
34 |
int end = templine.lastIndexOf("from"); |
35 |
int begin = templine.lastIndexOf("[Loaded")+7; |
36 |
String className = templine.substring(begin,end).replace(".", "/").trim(); |
37 |
depencyClass.add(className); |
38 |
templine= br.readLine(); |
40 |
JarFile zipIn = new JarFile(mainJar); |
41 |
InputStream readin = null; |
42 |
JarOutputStream jos = new JarOutputStream(new FileOutputStream("rt.jar")); |
43 |
JarInputStream jis = new JarInputStream(new FileInputStream(mainJar)); |
44 |
JarEntry entry = jis.getNextJarEntry(); |
46 |
String name = entry.getName(); |
47 |
//remove the .class suffix. |
48 |
name = name.substring(0,name.lastIndexOf(".")); |
49 |
if(depencyClass.contains(name)) { |
50 |
//put an entry record and write the binary data |
51 |
jos.putNextEntry(entry); |
52 |
readin = zipIn.getInputStream(entry); |
53 |
byte[] temp = new byte[4096]; |
54 |
int count = readin.read(temp); |
56 |
jos.write(temp, 0, count); |
57 |
count = readin.read(temp); |
61 |
entry = jis.getNextJarEntry(); |
1 |
运行下面Java命令,来生产简化版的rt.jar |
1 |
java test.ReduceJRE "F:\Program Files\Java\jre7\lib\rt.jar" "F:\Program Files\Java\jre7\lib\classdepency.txt" |
会在当前目录下生产一个精简版的rt.jar,用这个简化的rt.jar替代原来的rt.jar, 然后绑定JRE和桌程序一起发布。
这里有个需要主意的事项就是内部类的class文件是否需要特殊处理, 结论是不需要特殊处理.
因为我们做了完全的回归测试,用到的所有类(包括内部类),都已经加装了。
如果发现一个类有多个内部类而classdepenency.txt里面却显示只有一个内部类被加装,那是因为非静态内部类,只有在用到的情况下,才会加装。
既然我们的回归测试时都没有用到它,那么就说明是不需要的,因此内部类也不需要特殊考虑.
2.这里给出一个gc输出,要求给出一个你认为最可能的启动JVM参数,并说明为什么?
Heap
def new generation total 6464K, used 115K [0x34e80000, 0x35580000, 0x35580000)
eden space 5760K, 2% used [0x34e80000, 0x34e9cd38, 0x35420000)
from space 704K, 0% used [0x354d0000, 0x354d0000, 0x35580000)
to space 704K, 0% used [0x35420000, 0x35420000, 0x354d0000)
tenured generation total 18124K, used 8277K [0x35580000, 0x36733000, 0x37680000)
the space 18124K, 45% used [0x35580000, 0x35d95758, 0x35d95800, 0x36733000)
compacting perm gen total 16384K, used 16383K [0x37680000, 0x38680000, 0x38680000)
the space 16384K, 99% used [0x37680000, 0x3867ffc0, 0x38680000, 0x38680000)
ro space 10240K, 44% used [0x38680000, 0x38af73f0, 0x38af7400, 0x39080000)
rw space 12288K, 52% used [0x39080000, 0x396cdd28, 0x396cde00, 0x39c80000)
首先,这是一个client JVM生产的heap信息,因为加入-Server后得到的分代的标识都和例子很不一样.
但是对于很多非服务器的桌面系统默认运行的时候都是-client,所以不能确定是否指定了-client,只知道是运行在client JVM中.
对于Tenured Generation 当前大小=0x36733000-0x35580000=18124K=17.69921875M 总大小=0x37680000-0x35580000=33M
对于def new generation 新生代的内存总是一次性申请完的, 所以当前大小总是和总大小相等的,总大小=0x35580000-0x34e80000=7M
新生代:老年代=7:33 不是一个能够使用-XX:NewRatio来按比例分配的结果.
JVM 默认的比例是 新生代:老年代=1:2, 也和样例不符合,所以也不是默认值.
推测是加入了-Xmn7M来控制新生代,因此堆的最大值就是-Xmx40M。
对于老年代:初始大小=0x35d95758-0x35580000=8M,所以-Xms=15M
在新生代内部 s0:s1:eden=1:1:8 符合-XX:SurvivorRatio=8的分配结果,但是这个也是新生代内部默认的分配比例,所以不能确定是否指定了-XX:SurvivorRatio=8
对于Perm gen , 总大小=0x38680000-0x37680000=16M,初始大小=0x3867ffc0-0x37680000=15M
样例是GC的详细信息,所以肯定使用了 -XX:+PrintGCDetails
总结如下: 方括号里的参数是不确定的,可有可无.
-XX:+PrintGCDetails -XX:MaxPermSize=16M -XX:PermSize=15M -Xmx40M -Xms15M -Xmn7m [-XX:SurvivorRatio=8] [-client]
- bug终结者 团队作业第二周
bug终结者 团队作业第二周 我们小组选取游戏"开心消消乐",回答问题: 1. 此类软件是什么时候开始出现的, 这些软件是怎么说服你(陌生人)成为他们的用户的? 他们的目标都是盈利 ...
- 《团队作业第二周》五小福团队作业——UNO
<团队作业第二周>五小福团队作业--UNO 一.修改完善上周提交的需求规格说明书 THE FIRST改变 首先:我们组的博客无小组分工及占比,这是第一个问题,当时我们在写博客的时候由于很多 ...
- 2017-2018-2 1723《程序设计与数据结构》第九周作业 & 第二周结对编程 总结
作业地址 第九次作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1878 (作业界面已评分,可随时查看,如果对自己的评分有意 ...
- 绿洲作业第二周 - Y3每日中文学习任务清单
1. 本周仍是古诗学习周,老师已在“最美诵读”上布置本周需完成的任务,请孩子在“最美诵读”小程序中,结合老师发的学习任务清单,合理安排时间进行学习.如果孩子另有学习安排,可在周日(2.23)23:59 ...
- 团队作业-第二周-SRS文档
移动课堂点名的用例图:
- 团队作业—第二周—SRS
一.系统整体用例图: 二.用户用例图: 三.医院用例图:
- FJUT寒假作业第二周C题解(位运算)
题目来源:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P2 题意比较好理解.如果直接按题目要求一步一解.一定超时.作为一个懒人也不会这么暴力一个肯 ...
- FJUT寒假作业第二周G题解快速幂
题目来源:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P6 题意:求n个数字的乘积对c取摸.主要就是有快速幂扩展到广义幂的过程. 首先题目 ...
- Linux内核分析作业第二周
操作系统是如何工作的 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.函数调用堆栈 1.计算机工作三 ...
随机推荐
- Eclipse中部署hadoop2.3.0
1 eclipse中hadoop环境部署概览 eclipse 中部署hadoop包括两大部分:hdfs环境部署和mapreduce任务执行环境部署.一般hdfs环境部署比较简单,部署后就 可以在ecl ...
- CSS系列:长度单位&字体大小的关系em rem px
em是相对长度单位.相对于当前对象内文本的字体尺寸.如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸. 任意浏览器的默认字体高都是16px.所有未经调整的浏览器都符合: 1em=1 ...
- Spring+Mybatis+MySql+Maven 简单的事务管理案例
利用Maven来管理项目中的JAR包,同时使用Spring在业务处理层进行事务管理.数据库使用MySq,数据处理层使用Spring和Mybatis结合. 本案例代码主要结构如图: 1.数据库脚本 -- ...
- FAQ软件卸载
今天安装了一个PDF 编辑软件pdftk,下载时提示有50多M,感觉不好用,卸载后提示释放空间只有2M,郁闷了.上网查寻,如下命令 sudo dpkg -p package_name卸载软件包及其配置 ...
- WEB系统开发
最近根据项目组需求做了web工作流程系统,就是一个简单的web管理系统,取代原先使用的excel表格,在VS2008下面开发,数据库使用Mysql,使用Mysql-connecte 5.0与数据库连接 ...
- WEB安全攻防学习内容
一.网络安全篇 TCP/IP协议初识 Linux操作系统基础 网络漏洞扫描与信息收集 口令攻击 服务安全 日志安全 安全基线加固 防火墙vpn安全接入 网络无线原理和安全防护 二.编程篇 初识Pyth ...
- XPath学习:轴(14)——总结
原文地址:http://www.cnblogs.com/zhaozhan/archive/2009/09/10/1564396.html XPath 是一门在 XML 文档中查找信息的语言.XPath ...
- Delphi 如何清除动态数组的内存?
SetLength(glb_IndexConfig,); FreeAndNil(glb_IndexConfig);
- android studio 编程中用到的快捷键
1.Ctrl+Alt+T可以把代码包在一块内,例如try/catch Version:0.9 StartHTML:-1 EndHTML:-1 StartFragment:0000000111 EndF ...
- Linux下安装Xdebug
为了调试PHP程序,安装一下xdebug. 官方网址: http://www.xdebug.org 首先下载xdebug2.1.0,在官方首页下载源代码,下载回来的文件名是:xdebug-2.1.0. ...