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文件里记录的所有类.下面是程序的代码.

01 package test;
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;
13  
14  
15 public class ReduceJRE {
16  
17     public static void main(String[] args) throws Exception {
18         String mainJar = null;
19         String classDenpdencyFile = null;
20         if(args!=null && args.length==2)
21         {
22             mainJar = args[0];
23             classDenpdencyFile = args[1];
24         }
25         else {
26             mainJar = "F:Program FilesJavajre7librt.jar";
27             classDenpdencyFile = "F:Program FilesJavajre7libclassdepency.txt";
28         }
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();
39         }
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();
45         while(entry!=null) {
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);
55                 while (count != -1) {
56                         jos.write(temp, 0, count);
57                         count = readin.read(temp);
58                 }
59                 readin.close();
60             }
61             entry = jis.getNextJarEntry();
62         }
63         jis.close();
64         jos.close();
65     }
66 }
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]

JVM培训作业第二周的更多相关文章

  1. bug终结者 团队作业第二周

    bug终结者 团队作业第二周 我们小组选取游戏"开心消消乐",回答问题: 1. 此类软件是什么时候开始出现的, 这些软件是怎么说服你(陌生人)成为他们的用户的? 他们的目标都是盈利 ...

  2. 《团队作业第二周》五小福团队作业——UNO

    <团队作业第二周>五小福团队作业--UNO 一.修改完善上周提交的需求规格说明书 THE FIRST改变 首先:我们组的博客无小组分工及占比,这是第一个问题,当时我们在写博客的时候由于很多 ...

  3. 2017-2018-2 1723《程序设计与数据结构》第九周作业 & 第二周结对编程 总结

    作业地址 第九次作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1878 (作业界面已评分,可随时查看,如果对自己的评分有意 ...

  4. 绿洲作业第二周 - Y3每日中文学习任务清单

    1. 本周仍是古诗学习周,老师已在“最美诵读”上布置本周需完成的任务,请孩子在“最美诵读”小程序中,结合老师发的学习任务清单,合理安排时间进行学习.如果孩子另有学习安排,可在周日(2.23)23:59 ...

  5. 团队作业-第二周-SRS文档

    移动课堂点名的用例图:

  6. 团队作业—第二周—SRS

    一.系统整体用例图: 二.用户用例图: 三.医院用例图:

  7. FJUT寒假作业第二周C题解(位运算)

    题目来源:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P2 题意比较好理解.如果直接按题目要求一步一解.一定超时.作为一个懒人也不会这么暴力一个肯 ...

  8. FJUT寒假作业第二周G题解快速幂

    题目来源:http://210.34.193.66:8080/vj/Contest.jsp?cid=161#P6     题意:求n个数字的乘积对c取摸.主要就是有快速幂扩展到广义幂的过程. 首先题目 ...

  9. Linux内核分析作业第二周

    操作系统是如何工作的 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.函数调用堆栈 1.计算机工作三 ...

随机推荐

  1. 从JAVA客户端访问Redis示例(入门)

    转自:http://blog.csdn.net/kkdelta/article/details/7217761 本文记录了安装Redis和从JAVA端访问Redis的步骤 从http://downlo ...

  2. git 创建branch分支

    开发者user1 负责用getopt 进行命令解析的功能,因为这个功能用到getopt 函数,于是将这个分支命名为user1/getopt.(1)确保是在开发者user1的工作区中cd /home/j ...

  3. NBUT 1673 迷宫问题(DP)

    [1673] 迷宫问题 时间限制: 1000 ms 内存限制: 65535 K 问题描述 Alex的猫咪不小心走进了迷宫,Alex为了心爱的猫咪,决定进入迷宫去解救他的猫咪. 已知猫咪坐标为(n - ...

  4. 【转】const和static readonly

    我们都知道,const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等.在多数情况下可以混用.二者本质的区别在于,const的值是在编译期间确定的,因此只能在声 ...

  5. (6) 如何用Apache POI操作Excel文件-----POI-3.10的一个和注解(comment)相关的另外一个bug

    如果POI-3.10往一个工作表(sheet)里面插入数据的话,需要注意了,其有一个不太被容易发现的bug. 被插入的工作表(sheet)里面的单元格没有包含任何的注解(comment)的时候,插入一 ...

  6. C#winform中TrackBar的使用

    1.手动设置高度(宽):把AutoSize属性设为false 2.重要的事件:Scroll事件和和ValueChanged事件 3.由于TrackBar的Value类型为int,若绑定数据项的最小精度 ...

  7. [转]LaTeX处女级入门命令语法集

    1.LaTeX文件的框架如下: \documentclass{article} \begin{document} This is the body of the article \end{docume ...

  8. Twos Complement Representation

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION Like sign magnitude, ...

  9. Delphi出现“borland license information was found,but it is not valid for delphi”的错误,无法运行的解决方法

    1) 删除文件: C:\documents and settings\<username>\.borland\registry.slm,如果在win8或在win7下,即C:\Users\H ...

  10. App Previews操作经验

    App Previews操作经验 http://www.cocoachina.com/ios/20140924/9741.html http://www.cocoachina.com/bbs/read ...