博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
精简JRE的思路初探
阅读量:6174 次
发布时间:2019-06-21

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

引言: 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
classes = new ArrayList
(); 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等来进行等。会更加可控和灵活。

   

你可能感兴趣的文章
Dsicuz x2.5、X3、X3.2如何去掉域名后面的/forum.php
查看>>
java.util.zip.DataFormatException: invalid distance too far back
查看>>
iml文件
查看>>
[汇编] 2数相加极简单版
查看>>
oracle登录错误:ORA-28000: the account is locked 解决方法
查看>>
VS调试Tip集结
查看>>
half extents
查看>>
New release iTextSharp 3.1.4 (2006-08-28)
查看>>
C# Socket系列三 socket通信的封包和拆包
查看>>
WinDbg 命令三部曲:(二)WinDbg SOS 扩展命令手册
查看>>
景德镇特色的部门级别与权限
查看>>
Eclipse 打包过滤 Log.e
查看>>
MVVM架构~knockoutjs系列之验证信息自定义输出~再续
查看>>
DB2 Vs MySQL系列 | 体系架构对比
查看>>
32.4. redis-benchmark 测试工具
查看>>
Elaticsearch REST API常用技巧
查看>>
MySQL相关命令与备份
查看>>
HTML,CSS编码规范
查看>>
Woobuntu woobuntu_build.sh hacking
查看>>
Android 系统内置App JNI
查看>>