java jre精简_精简 jre

jre 文件结构

-bin (启动jvm虚拟机中必要的exe和dll)

​ --java.exe (java主程序,用于启动窗口程序或非阻塞程序 )

​ --javaw.exe (用于启动 窗口程序或非阻塞程序 程序)

​ --其他exe (基本都可删除)

​ --server (jvm虚拟机的存放目录)

​ ---jvm.dll(jvm 虚拟机)

​ --其他dll

-lib (Java 运行环境所使用的核心类库、属性设置和资源文件)

​ --rt.jar (java提供的基本类库,包含了 Java 平台的核心 API。重点精简对象)

​ --其他资源

精简jre

准备jre将需要精简的版本的 jre 拷贝一份到一个你能找到的地方(安装Java后,jre一般位于 C:\Program Files\Java 下 )

拷贝需要运行的项目到jre同级目录

精简jre目录

在jre目录下,除了bin目录,lib目录的其他文件均可删除

精简bin目录

为了方便操作可删除 jre 文件夹名称中的版本信息,如 jre1.8.0_191 删除后为 jre打开 cmd,进入jre 文件夹所在的目录,使用本目录的jre运行你的项目,如:

一般情况运行你的项目是:java -jar xxx.jar 或 javaw -jar xxx.jar

现在你应该:jre\bin\java.exe -jar xxx.jar 或 jre\bin\javaw.exe -jar xxx.jar使用文件管理器打开bin文件夹

在运行项目的同时,逐一删除bin文件夹下的文件,能删除的表示不需要,可以都删除

删除完成后 bin 目录的精简完成,如下:

精简lib文件夹

在jre1.8中 rt.jar 类库就占了52.1 MB,所以精简lib文件的主要任务就是精简 rt.jar

精简除 rt.jar 外的其他文件(如果对精简要求不高,或者嫌麻烦的可省略本步骤)

逐个将 lib 下的文件剪切至其它地方,让后运行项目,若项目无法成功运行,则将该文件粘贴回本地

精简rt.jar

提取需要的类

可借助 -ferbose 命令,查看虚拟机在运行 Java 程序时所加载的所有类

java -jar -verbose:class xxx.jar >>class.txt

然后运行一遍项目的所有功能(尽可能的所有功能都运行一遍)

在 class.txt 中可以查看到该项目所需要的所有类

重新打包 rt.jar

得到rt需要的类的路径

class.txt 中的条目都形同 [Loaded java.lang.Object from C:\Users\john\Desktop\a\jre\lib\rt.jar] ,我们需要获取每个类的路径,如 java\lang\Object ,以方便我们后面复制所需要的类仅读取 含有 rt.jar 的条目

提取条目中的 java.lang.Object

将 . 修改为 \

代码如下:

java:

public static void get_class_path_file(String class_file_path,

String re_class_file_path) {

try {

BufferedReader in = new BufferedReader(new InputStreamReader(

new FileInputStream(class_file_path), "utf-8"));

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(

new FileOutputStream(re_class_file_path), "utf-8"));

String str = null;

while ((str = in.readLine()) != null) {

if((str.indexOf("rt.jar") != -1) && (str.indexOf("Loaded") != -1)) {

String class_name = str.substring(8, str.indexOf("from")-1);

String class_path = class_name.replace(".", "\\");

out.write(class_path);

out.newLine();

}

}

out.flush();

in.close();

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

提取之后结果如下:

java\lang\Object

java\io\Serializable

java\lang\Comparable

java\lang\CharSequence

java\lang\String

java\lang\reflect\AnnotatedElement

java\lang\reflect\GenericDeclaration

java\lang\reflect\Type

java\lang\Class

java\lang\Cloneable

java\lang\ClassLoader

java\lang\System

java\lang\Throwable

java\lang\Error

java\lang\ThreadDeath

java\lang\Exception

......

解压rt.jar

使用压缩工具解压 rt.jar 得到 rt 文件夹

复制所需要的类到新的文件夹

代码如下:

Java:

public static int deal_class(String class_path_file, String rt_dir, String new_rt_dir) {

int sum = 0;

File used_class = new File(class_path_file);

if (used_class.canRead()) {

String line = null;

try{

LineNumberReader reader = new LineNumberReader(new InputStreamReader(new FileInputStream(used_class),

"UTF-8"));

while ((line = reader.readLine()) != null) {

line = line.trim();

int dirpos = line.lastIndexOf("/");

if (dirpos > 0) {

String dir = new_rt_dir + line.substring(0, dirpos);

File fdir = new File(dir);

if (!fdir.exists())

fdir.mkdirs();

String sf = rt_dir + line + ".class";

String of = new_rt_dir + line + ".class";

boolean copy_ok = copy_file(sf.trim(), of.trim());

if (copy_ok)

sum++;

else {

System.out.println(line);

}

}

}

} catch (IOException e){

e.printStackTrace();

}

}

return sum;

}

public static boolean copy_file(String file1, String file2) {

try

{

java.io.File file_in = new java.io.File(file1);

java.io.File file_out = new java.io.File(file2);

FileInputStream in1 = new FileInputStream(file_in);

FileOutputStream out1 = new FileOutputStream(file_out);

byte[] bytes = new byte[1024];

int c;

while ((c = in1.read(bytes)) != -1)

out1.write(bytes, 0, c);

in1.close();

out1.close();

return (true);

} catch (IOException e) {

e.printStackTrace();

return (false);

}

}

重新压缩新的 rt.jar

使用压缩工具将新的 rt 文件下的文件压缩成rt.zip (注意:只能是zip格式,而且压缩后的文件点开后不能有 rt 文件夹)

然后将文件名修改为 rt.jar

或者直接使用下面的代码压缩:

public static void get_rt_jar(String rt_dir,String rt_jar_path){

try {

FileOutputStream fos3 = new FileOutputStream(new File(rt_jar_path));

File file = new File(rt_dir);

ZipOutputStream zos = new ZipOutputStream(fos3);

ZipUtils.dir_to_zip(file, zos, "");

zos.close();

} catch(Exception e) {

e.printStackTrace();

}

}

private static void dir_to_zip(File sourceFile, ZipOutputStream zos, String name)

throws Exception {

boolean KeepDirStructure = true;

byte[] buf = new byte[2048];

if (sourceFile.isFile()) {

zos.putNextEntry(new ZipEntry(name));

int len;

FileInputStream in = new FileInputStream(sourceFile);

while ((len = in.read(buf)) != -1) {

zos.write(buf, 0, len);

}

// Complete the entry zos.closeEntry();

in.close();

} else {

File[] listFiles = sourceFile.listFiles();

if (listFiles == null || listFiles.length == 0) {

if (KeepDirStructure) {

zos.putNextEntry(new ZipEntry(name + "/"));

zos.closeEntry();

}

} else {

for (File file : listFiles) {

if (KeepDirStructure) {

if (!name.equals("")){

dir_to_zip(file, zos, name + "/" + file.getName());

}else {

dir_to_zip(file, zos, file.getName());

}

} else {

dir_to_zip(file, zos, file.getName());

}

}

}

}

}

使用方式如下:

public static void get_rt(){

String rt_path = "C:\\Users\\john\\Desktop\\jre\\lib\\rt";

String jar_path = rt_path + ".jar";

get_rt_jar(rt_path, jar_path);

}

让后将得到的 rt.jar替换掉原来 lib 文件夹下的 rt.jar

运行程序,运行成功

我们就得到了一个精简版的 jre, 大小一般在 5MB 左右

附:运行程序提示无法找到或加载类的解决办法:

有时候由于在 提取需要的类 的时候我们没有将所有功能执行完,或者其他原因,在使用精简 jre 运行我们的程序时会提示 无法找到或加载类 ,这时我们应该:解压 精简 jre 中的rt.jar

在 未精简的 rt 文件夹中找到 无法找到或加载类 提示中的类

将其拷贝至 精简后的 rt 文件夹中

重新压缩 rt.jar

运行程序,重复以上步骤,直到不在有该提示即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值