0. 思路:
1)把自己的应用程序打包成可运行的jar包
2)通过jar命令运行这个jar包
3)把jar包所需要的类全部打印到文本文件中
4)把上一步产生的类从文件中提取出来重新打包
5)去掉jre中bin和lib目中下的不需要的文件和目录
1. 打包运行,使用下面bat将所用到的类全部输出到文件中
@echo off
set path=.\jre\bin
.\jre\bin\java -jar -verbose:class lottery.jar > class.txt
@pause
2. class.txt文件处理
class.txt文件格式如下
[Opened D:\baiduyundownload\Lottery\jre\lib\rt.jar]
[Loaded java.lang.Object from D:\baiduyundownload\Lottery\jre\lib\rt.jar]
[Loaded java.io.Serializable from D:\baiduyundownload\Lottery\jre\lib\rt.jar]
[Loaded java.lang.Comparable from D:\baiduyundownload\Lottery\jre\lib\rt.jar]
[Loaded java.lang.CharSequence from D:\baiduyundownload\Lottery\jre\lib\rt.jar]
[Loaded java.lang.String from D:\baiduyundownload\Lottery\jre\lib\rt.jar]
这里使用到的是rt.jar和charsets.jar,将其分别抽取出来,抽取出来的格式如下:
sun/nio/cs/ext/ExtendedCharsets
sun/nio/cs/ext/GBK
sun/nio/cs/ext/DoubleByteDecoder
sun/nio/cs/ext/GBK$Decoder
sun/nio/cs/ext/DoubleByteEncoder
sun/nio/cs/ext/GBK$Encoder
抽取步骤:
grep rt.jar class.txt > rt.txt
# 32位的jvm,使用rt.jar有下面这种格式
grep "from shared objects file" class.txt >> rt.txt
grep charsets class.txt > charsets.txt
vi命令
%s/\[Loaded //g # 替换掉行头
%s/ from *.*//g # 替换掉行尾
%s/\./\//g # .替换成/
3. 重新打包
1)首先将jre目录中的rt.jar, charsets.jar分别解压到输入目录,运行如下代码
参数:./data/rt.txt ./data/rt ./output/rt
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
public class ReduceClasses {
/**
* 文件拷贝
*
* @param srcFileName
* @param destFileName
* @return
*/
public static boolean copy(String srcFileName, String destFileName) {
try {
FileInputStream in = new FileInputStream(new File(srcFileName));
FileOutputStream out = new FileOutputStream(new File(destFileName));
try {
byte[] bytes = new byte[1024];
int c = -1;
while ((c = in.read(bytes)) != -1)
out.write(bytes, 0, c);
in.close();
out.close();
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
} catch (Exception e) {
e.printStackTrace();
return (false);
}
return (true);
}
/**
* 读取路径,copy
*
* @param classFile
* @param srcRtDir
* @param destRtDir
* @return
* @throws IOException
*/
public static int dealClass(String classFile, String srcRtDir, String destRtDir) {
int sucessCount = 0;
try {
LineNumberReader reader = new LineNumberReader(new FileReader(new File(classFile)));
try {
String line = null;
while ((line = reader.readLine()) != null) {
int pos = line.lastIndexOf("/");
if (pos > 0) {
File dir = new File(destRtDir + line.substring(0, pos));
if (!dir.exists())
dir.mkdirs();
String srcFileName = srcRtDir + line + ".class";
String destFileName = destRtDir + line + ".class";
if (copy(srcFileName, destFileName))
sucessCount++;
else {
System.out.println(line);
}
}
}
} finally {
if (reader != null) {
reader.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return sucessCount;
}
public static void main(String[] args) {
if (args == null || args.length != 3) {
System.err.println("Usage: ReduceClasses classFile srcRtDir destRtDir");
}
String classFile = args[0]; // 运行JAR生成的,应用程序所需类的txt文件
String srcRtDir = args[1]; // rt.jar解压后的目录
String destRtDir = args[2]; // 抽取的类存放目录
if (!srcRtDir.endsWith("/")) {
srcRtDir += "/";
}
if (!destRtDir.endsWith("/")) {
destRtDir += "/";
}
System.out.print("Success Count: " + dealClass(classFile, srcRtDir, destRtDir));
}
}
2)将原有rt目录中的META-INF拷贝到新的rt目录中去,进入新的rt目录,使用rar打成zip包,然后重命名为rt.jar. charsets同样处理
4. 精简jre中其他无用文件
1)新建jre目录,在其中建两个子目录bin和lib
2)将新生成的rt.jar和charsets.jar拷贝到lib中
3)从原生jre的lib中拷贝出i386和zi两个子目录,其中zi里面只保留America和Asia两个目录
4)原生jre的lib中除了库文件和文件夹之外的所有属性文件都要拷贝到新的lib中
5)在运行jar包时查看该进程使用到的dll,将这些dll保存到新的bin目录中去
5. 查看运行进程所用使用到的dll
tasklist /m >dll.txt &&dll.txt
java.exe 6376 ntdll.dll, kernel32.dll, KERNELBASE.dll,
ADVAPI32.dll, msvcrt.dll, sechost.dll,
RPCRT4.dll, jvm.dll, USER32.dll, GDI32.dll,
LPK.dll, USP10.dll, WINMM.dll, IMM32.DLL,
MSCTF.dll, verify.dll, java.dll, PSAPI.DLL,
zip.dll, swt-win32-3659.dll, ole32.dll,
OLEAUT32.dll, comdlg32.dll, SHLWAPI.dll,
COMCTL32.dll, SHELL32.dll, WININET.dll,
urlmon.dll, CRYPT32.dll, MSASN1.dll,
iertutil.dll, uxtheme.dll,
QvodExtend_x64.dll, VERSION.dll,
WS2_32.dll, NSI.dll, dwmapi.dll,
CRYPTBASE.dll, CLBCatQ.DLL
6. 结果:
我的jre中:
bin |
---
client |
--- jvm.dll
java.dll
java.exe
verify.dll
zip.dll
精简完的jre是4M多
7. 参考文章
http://yaojialing.iteye.com/blog/1067409