在网络上搜索下便能看到有不少讨论这个问题的文章。个人认为,JRE最好是能向下兼容,于是不同的程序可以在自己的程序中配置所需要的JRE版本。这样就不再会因为用户机器上的JRE版本问题而烦恼。同时,Java开发者所能做的就是尽量精简JRE以满足自己产品运行为最低要求。
本文將介绍我成功简化rt.jar包的过程。
正文:
操作流程简介:
首先,在Windows环境下,准备好需要精简的rt.jar所属的JRE文件夹。
接着,需要在Windows环境下,通过命令在准备好的的JRE环境中运行我们所需要的程序,程序的每个功能最好都能执行,以满足每个需要被调用的包能被自动记录在一个文本文件中。
然后,编写一个程序按照记录將解压缩後的rt.jar包中所需要的类及其所属文件目录结构完整的复制到一个新的rt文件夹中(默认命名为ort(Objecct rt的意思))。
最后,打包ort文件为rt.jar并替换之前准备好的JRE/lib/ 下的rt.jar文件。(原来的rt.jar文件有40多MB,简化後最小可能只有几MB)。
操作流程详述:
我们需要在jre文件见的父文件夹(即,上级文件夹)下创建.txt文本文件,并写入:
“这样程序使用的就是当前目录下的jre,程序运行后,最好把所有的功能使用一遍,这样输出了一个文件usedClasses.txt,里面有所有需要的class,其格式如下:
[Opened D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.Object from D:\data\dict\jre\lib\rt.jar]
[Loaded java.io.Serializable from D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.Comparable from D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.CharSequence from D:\data\dict\jre\lib\rt.jar]
[Loaded org.apache.lucene.index.CompoundFileReader$FileEntry from file:/D:/data/dict/dict.jar]
我们依照这个文件来裁剪rt.jar:“
由于在Ubuntu下我使用GUN Emacs 23来修改usedClasses.txt文件的内容,以满足之后程序读取的需要(这算是我第一次正式使用Emacs吧)。第一步,我用Gun Emacs 23打开usedClasses.txt文件。
第二步,选择Edit->Replace->Replace String...,键入将被替换的[Loaded 并确认,再键入用于替换它的回车(即,等同于删去[Loaded 这个关键字段)。
第三步,选择Edit->Replace->Replace Regexp...,通过正则表达式from.*来查找from到]的语句。并替换
第四步,删掉最开头的 [Opened 。删掉其他多余的不包含.class类的语句。
第五步,保存文件。这样usedClasses.txt便准备好了。
注释:在Emacs中 `\n' here doesn't match a newline; to do that, type C-q C-j instead(C代表Ctrl键)按下Ctrl不放,再接着依次按qj键。(根多关于Emacs可以参考:http://hi.baidu.com/limp_t/blog/item/3bc60f54d868b0143a2935bf.html)
下面修改之前提到的文章中的Java代码。因为我发现他们还不能够成功拷贝二进制文件。
首先,我分享将要用到的,由我封装的IO读写类的部分用到的方法的代码,其他的代码可以省去,足够作为一个完整的类。
然后,我在分享我修改後的拷贝.class文件及其目录结构的代码。
InputOutput.java:
package com.wordpress.iwillaccess.classes.global;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class InputOutput {
private static String _fileLocation;
private static String _fileName;
private static String _fileDirectory;
private static String _fileContent;
private static byte[] _byte;
/**
* @return the _fileDirection
*/
public String get_fileLocation() {
return _fileLocation;
}
/**
* @return the _fileName
*/
public String get_fileName() {
return _fileName;
}
/**
* @return the _fileDirectory
*/
public String get_fileDirectory() {
return _fileDirectory;
}
/**
* @return the _fileContents
*/
public String get_fileContent() {
return _fileContent;
}
/**
* @return the _byte
*/
public byte[] get_byte() {
return _byte;
}
/**
* @param fileDirection
* the _fileDirection to set
*/
private static synchronized void set_fileLocation(String fileLocation) {
_fileLocation = fileLocation;
}
/**
*
* @param fileName
* the _fileName to set
*/
private static synchronized void set_fileName(String fileName) {
_fileName = fileName;
}
/**
*
* @param fileLocation
* the _fileLocation to set
* @param fileName
* the _fileName to set < br >
* < br >
* fileLocation and fileName is the _fileDirectory to set.
*/
public synchronized void set_fileDirectory(String fileLocation,
String fileName) {
set_fileLocation(fileLocation);
set_fileName(fileName);
_fileDirectory = fileLocation + fileName;
}
/**
*
* @param fileDirectory
* the _fileDirectory to set < br >
* < br >
* _fileDirectory = _fileLocation + _fileName; < br >
* _fileLocation and _fileName will be set automatically in this
* method. < br >
*/
public synchronized void set_fileDirectory(String fileDirectory) {
set_fileLocation(fileDirectory.substring( 0, fileDirectory
.lastIndexOf( "/") + 1));
set_fileName(fileDirectory
.substring(fileDirectory.lastIndexOf( "/") + 1));
_fileDirectory = fileDirectory;
}
/**
* @param fileContents
* the _fileContents to set
*/
public synchronized void set_fileContent(String fileContent) {
_fileContent = fileContent;
}
/**
* @param _byte
* the _byte to set
*/
private synchronized void set_byte( byte[] _byte) {
InputOutput._byte = _byte;
}
public InputOutput() {
// TODO Auto-generated constructor stub
}
/**
* check if the file is exist or not
*
* @param fileDirectory
* the _fileDirectory to set, and the directory of the file will
* be checked.
* @return true: file is exist; < br >
* false: file is not exist.
*/
public boolean checkIfFileExist(String fileDirectory) {
set_fileDirectory(fileDirectory);
File file = new File(get_fileDirectory());
// System.out.println("file.exists():" + file.exists());
return file.exists();
}
//…………
//……省去的无关方法的代码………
//…………
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > use the set_fileDirectory(), set_byte() and
* checkIfFileExist(String fileDirectory) methods first < br >
* to set a righdis.readFully(b)t file directory and file content < br >
* before using this method; < br >
* < blockquote >
*/
public synchronized void DataInputFully() {
if (get_fileLocation() != null && get_fileName() != null
&& get_fileContent() != null && get_byte() != null) {
try {
FileOutputStream fos = new FileOutputStream(get_fileDirectory());
DataOutputStream dos = new DataOutputStream(fos);
dos.write(get_byte());
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println( "fileLocation:" + get_fileLocation()
+ "; or fileName:" + get_fileName() + "; or byte[]:"
+ get_byte() + " is null.");
}
}
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > please use set_fileDirectory() to set the file directory,
* and use checkIfFileExist(String fileDirectory) first < br >
* before using this method. < br >
* </ blockquote >
*
* @param b
* the _byte to set
*/
public void DataInputFully( byte[] b) {
set_byte(b);
DataInputFully();
}
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > create a file, whose directory as < code > fileDirectory </ code >
* and file content as < code > get_byte() </ code > . < br >
* Use checkIfFileExist(String fileDirectory) first < br >
* </ blockquote >
*
* @param fileDirectory
* the _fileDirectory to set < br >
* @param b
* the _byte to set, contains the content of file.
*/
public void DataInputFully(String fileDirectory, byte[] b) {
set_fileDirectory(fileDirectory);
set_byte(b);
DataInputFully();
}
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > create file named < code > fileName </ code > in
* < code > fileLocation </ code > input < code > get_byte() </ code > to file named as
* < code > fileName </ code > in < code > fileLocation </ code > . < br >
* Use checkIfFileExist(String fileDirectory) first < br >
* </ blockquote >
*
* @param fileLocation
* the _fileLocation to set and will be used to set the
* _fileDirectory
* @param fileName
* the _fileName to set and will be used to set the
* _fileDirectory
* @param b
* the _byte to set and will be write to the file with
* _fileDirectory directory. _byte Contains the content of file.
*/
public void DataInputFully(String fileLocation, String fileName, byte[] b) {
set_fileDirectory(fileLocation, fileName);
set_byte(b);
DataInputFully();
}
/**
* Out put a file by using DataOutputStream class. < br >
* < br >
* NOTE: < br >
* < blockquote > use the set_fileDirectory() method first < br >
* to set a right file directory < br >
* before using this method; < br >
* </ blockquote >
*
* @return null:if fileDirectory is null; < br >
* file content byte[];
*/
public synchronized byte[] DataOutputFully() {
if (get_fileDirectory() != null) {
File file = new File(get_fileDirectory());
if (file.exists()) {
try {
FileInputStream fis;
fis = new FileInputStream(get_fileDirectory());
DataInputStream dis = new DataInputStream(fis);
byte[] b = new byte[dis.available()];
while (dis.available() > 0) {
dis.readFully(b);
// System.out.println(" :" + b.length);
}
set_byte(b);
String tmpStr = "";
for ( int i = 0; i < b.length; i++) {
tmpStr += String.valueOf(b[i]);
}
set_fileContent(tmpStr);
// System.out.println("\n" + get_fileContent() + "\n"
// + get_fileLocation() + "\n" + get_fileName());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return get_byte();
} else {
System.out.println( "fileDirectory:" + get_fileDirectory()
+ "; and the file is not exist.");
return null;
}
} else {
System.out.println( "fileDirectory:" + get_fileDirectory()
+ "; is null");
return null;
}
}
/**
* Out put a file, which directory as < code > fileDirectory </ code > , < br >
* by using DataOutputStream class. < br >
*
* @param fileDirectory
* the _fileDirectory to set and will be used to find the file,
* which is supposed to be opened. < br >
* @return byte[] _byte() the content of the chose file.
*/
public byte[] DataOutputFully(String fileDirectory) {
set_fileDirectory(fileDirectory);
return DataOutputFully();
}
/**
* Out put a file, which directory as < code > fileLocation </ code > plus
* < code > fileName </ code > , < br >
* by using DataOutputStream class. < br >
*
* @param fileLocation
* the _fileLocation to set and will be used to set the
* _fileDirectory
* @param fileName
* the _fileName to set and will be used to set the
* _fileDirectory
* @return byte[[] get_byte() the content of the chose file.Data
*/
public byte[] DataOutputFully(String fileLocation, String fileName) {
set_fileDirectory(fileLocation, fileName);
return DataOutputFully();
}
public static void main(String[] args) {
InputOutput io = new InputOutput();
io.set_fileDirectory( "/home/knowyourself1010/Tracker.class");
io.set_fileContent( "1234567890 abcdefg ABCDEFG 好的繁体字简体字复杂么?");
// io.DataInput();
System.out.println(io.DataOutput());
io.set_fileDirectory( "/home/knowyourself1010/file.class");
io.DataInput();
// io.set_fileContent("rfgadssssssssssssssdsaaaadwefewfefeferegrqedwdq");
// System.out.println(io.get_fileContent());
}
}
CopyUsefulClasses.java:
/**
*
*/
package com.wordpress.iwillaccess.tools;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import com.wordpress.iwillaccess.classes.global.InputOutput;
/**
* @author knowyourself1010
*
*/
public class CopyUsefulClasses {
// 文件拷贝
private static boolean copy(String sourceFileLocation,
String objectFileLocation, String fileName) {
try // must try and catch,otherwise will compile error
{
if (sourceFileLocation.substring(sourceFileLocation.length() - 1) != "/") {
sourceFileLocation += "/";
}
if ((objectFileLocation.substring(objectFileLocation.length() - 1)) != "/") {
objectFileLocation += "/";
}
InputOutput inputOutput = new InputOutput();
byte[] b = inputOutput
.DataOutputFully(sourceFileLocation, fileName);
inputOutput.DataInputFully(objectFileLocation, fileName, b);
return true; // if success then return true
} catch (Exception e) {
System.out.println( "Error!");
return false; // if fail then return false
}
}
// 读取路径,copy
private static int dealClass(String needfile, String sdir, String odir)
throws IOException {
int sn = 0; // 成功个数
if (odir.length() > 0 && sdir.length() > 0) {
if ((sdir.substring(sdir.length() - 1)) != "/") {
sdir += "/";
}
if (odir.substring(odir.length() - 1) != "/") {
odir += "/";
}
File usedclass = new File(needfile);
if (usedclass.canRead()) {
String line = null;
LineNumberReader reader = new LineNumberReader(
new InputStreamReader( new FileInputStream(usedclass),
"UTF-8"));
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.contains( ".") || line.contains( "/")) {
// format the direction from package name to path
String dir = line.replace( ".", "/");
// filter the file name.
String tmpdir = dir.substring( 0, dir.lastIndexOf( "/"));
String sourceFileLocation = sdir + tmpdir;
String objectFileLocation = odir + tmpdir;
String fileName = dir.substring(
dir.lastIndexOf( "/") + 1, dir.length())
+ ".class";
File fdir = new File(objectFileLocation);
if (!fdir.exists())
fdir.mkdirs();
boolean copy_ok = copy(sourceFileLocation,
objectFileLocation, fileName);
if (copy_ok)
sn++;
else {
System.out.println(line);
}
} else {
sn = - 1;
}
}
}
}
return sn;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
BufferedReader lineOfText = null;
// get need classes log file direction
System.out
.println( "needfile (file logged the full name of useful classes ):");
lineOfText = new BufferedReader( new InputStreamReader(System.in));
String needfile = lineOfText.readLine();
// get source folder direction
System.out
.println(needfile
+ " \n Source Folder Direction (the direction of the folder filled the classes need to be filtered.):");
lineOfText = new BufferedReader( new InputStreamReader(System.in));
String sdir = lineOfText.readLine();
// get object folder direction
System.out
.println(sdir
+ " \n Object Folder Direction (the direction of the folder used to fill the filtered classes.):");
lineOfText = new BufferedReader( new InputStreamReader(System.in));
String odir = lineOfText.readLine();
System.out.println(odir + " \n ");
int sn = dealClass(needfile, sdir, odir);
System.out.print(sn);
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
}
}
(在此感谢irc: ##java上朋友提示读写Binary文件的注意事项:不要用Reader方法!Char也不太支持哦。)
运行CopyUsefulClasses.java。首先输入usedClasses.txt的绝对路径,回车,在输入jre/lib/rt.jar解压後的rt文件夹所在的路径,回车,再输入ort(所要存放拷贝过来的有用的.class文件的文件夹)。然后等上几分中,期间会提示,你的产品程序所用到的jre不包含的类不存在,不用管,因为我们呢只拷贝rt文件中的.class文件。
最后將ort文件夹下面的所有文件加压缩为rt.zip文件,并改为rt.jar。
注意:1.是选中ort文件夹下所有子文件夹,而非选中ort文件夹,并压缩。
2.在Ubuntu10.10下如果选择压缩为jar格式文件,可能会少压缩进java.lang.Object.class等文件(估计是个bug),所以需要压缩为.zip再该类型为.jar。
最后,將要简化的jre中的rt.jar替换为这里压缩得到的rt.jar文件。我的只有2MB。
用 java -jar [您的jar程序路径]
来测试简化後的jre是否成功吧。
本文將介绍我成功简化rt.jar包的过程。
操作流程简介:
首先,在Windows环境下,准备好需要精简的rt.jar所属的JRE文件夹。
接着,需要在Windows环境下,通过命令在准备好的的JRE环境中运行我们所需要的程序,程序的每个功能最好都能执行,以满足每个需要被调用的包能被自动记录在一个文本文件中。
然后,编写一个程序按照记录將解压缩後的rt.jar包中所需要的类及其所属文件目录结构完整的复制到一个新的rt文件夹中(默认命名为ort(Objecct rt的意思))。
最后,打包ort文件为rt.jar并替换之前准备好的JRE/lib/ 下的rt.jar文件。(原来的rt.jar文件有40多MB,简化後最小可能只有几MB)。
操作流程详述:
(其中用到了来自网络的程序代码,当然经过我大量修改後才成功执行了任务。由于事隔几日,没有记下原代码作者信息,如果原代码作者看到,可以联系我,我将会加上引用注释)首先,在Windows下准备好for Windows版的完整JRE文件。(我的在C:/Program Files/Java/jdk1.6.0_20/jre,其中jre/bin/中的Java程序是.exe格式的)。所要精简的rt.jar在/jre/lib/目录下。先不拷贝这个jre文件。
重新搜索了下,那篇文章被到处引用,如:
http://www.kaiyuan8.org/Article/syaKuiwQVGqhnFgjCwcZ.aspx
http://www.cnitblog.com/Walter/articles/59164.html(仅仅作为举例,别无它意)
已经难寻出处了。
下面来讲讲我根据这篇文章精简的经历吧。
我们需要在jre文件见的父文件夹(即,上级文件夹)下创建.txt文本文件,并写入:
start jre/bin/java -jar -verbose:class 【改写成你打包成.jar的产品程序包路径,并去掉这句话两端的中括号】>>usedClasses.txt再將其.txt修改成.cmd。并执行。
pause
“这样程序使用的就是当前目录下的jre,程序运行后,最好把所有的功能使用一遍,这样输出了一个文件usedClasses.txt,里面有所有需要的class,其格式如下:
[Opened D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.Object from D:\data\dict\jre\lib\rt.jar]
[Loaded java.io.Serializable from D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.Comparable from D:\data\dict\jre\lib\rt.jar]
[Loaded java.lang.CharSequence from D:\data\dict\jre\lib\rt.jar]
[Loaded org.apache.lucene.index.CompoundFileReader$FileEntry from file:/D:/data/dict/dict.jar]
我们依照这个文件来裁剪rt.jar:“
由于在Ubuntu下我使用GUN Emacs 23来修改usedClasses.txt文件的内容,以满足之后程序读取的需要(这算是我第一次正式使用Emacs吧)。第一步,我用Gun Emacs 23打开usedClasses.txt文件。
第二步,选择Edit->Replace->Replace String...,键入将被替换的[Loaded 并确认,再键入用于替换它的回车(即,等同于删去[Loaded 这个关键字段)。
第三步,选择Edit->Replace->Replace Regexp...,通过正则表达式from.*来查找from到]的语句。并替换
第四步,删掉最开头的 [Opened 。删掉其他多余的不包含.class类的语句。
第五步,保存文件。这样usedClasses.txt便准备好了。
注释:在Emacs中 `\n' here doesn't match a newline; to do that, type C-q C-j instead(C代表Ctrl键)按下Ctrl不放,再接着依次按qj键。(根多关于Emacs可以参考:http://hi.baidu.com/limp_t/blog/item/3bc60f54d868b0143a2935bf.html)
下面修改之前提到的文章中的Java代码。因为我发现他们还不能够成功拷贝二进制文件。
首先,我分享将要用到的,由我封装的IO读写类的部分用到的方法的代码,其他的代码可以省去,足够作为一个完整的类。
然后,我在分享我修改後的拷贝.class文件及其目录结构的代码。
InputOutput.java:
package com.wordpress.iwillaccess.classes.global;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class InputOutput {
private static String _fileLocation;
private static String _fileName;
private static String _fileDirectory;
private static String _fileContent;
private static byte[] _byte;
/**
* @return the _fileDirection
*/
public String get_fileLocation() {
return _fileLocation;
}
/**
* @return the _fileName
*/
public String get_fileName() {
return _fileName;
}
/**
* @return the _fileDirectory
*/
public String get_fileDirectory() {
return _fileDirectory;
}
/**
* @return the _fileContents
*/
public String get_fileContent() {
return _fileContent;
}
/**
* @return the _byte
*/
public byte[] get_byte() {
return _byte;
}
/**
* @param fileDirection
* the _fileDirection to set
*/
private static synchronized void set_fileLocation(String fileLocation) {
_fileLocation = fileLocation;
}
/**
*
* @param fileName
* the _fileName to set
*/
private static synchronized void set_fileName(String fileName) {
_fileName = fileName;
}
/**
*
* @param fileLocation
* the _fileLocation to set
* @param fileName
* the _fileName to set < br >
* < br >
* fileLocation and fileName is the _fileDirectory to set.
*/
public synchronized void set_fileDirectory(String fileLocation,
String fileName) {
set_fileLocation(fileLocation);
set_fileName(fileName);
_fileDirectory = fileLocation + fileName;
}
/**
*
* @param fileDirectory
* the _fileDirectory to set < br >
* < br >
* _fileDirectory = _fileLocation + _fileName; < br >
* _fileLocation and _fileName will be set automatically in this
* method. < br >
*/
public synchronized void set_fileDirectory(String fileDirectory) {
set_fileLocation(fileDirectory.substring( 0, fileDirectory
.lastIndexOf( "/") + 1));
set_fileName(fileDirectory
.substring(fileDirectory.lastIndexOf( "/") + 1));
_fileDirectory = fileDirectory;
}
/**
* @param fileContents
* the _fileContents to set
*/
public synchronized void set_fileContent(String fileContent) {
_fileContent = fileContent;
}
/**
* @param _byte
* the _byte to set
*/
private synchronized void set_byte( byte[] _byte) {
InputOutput._byte = _byte;
}
public InputOutput() {
// TODO Auto-generated constructor stub
}
/**
* check if the file is exist or not
*
* @param fileDirectory
* the _fileDirectory to set, and the directory of the file will
* be checked.
* @return true: file is exist; < br >
* false: file is not exist.
*/
public boolean checkIfFileExist(String fileDirectory) {
set_fileDirectory(fileDirectory);
File file = new File(get_fileDirectory());
// System.out.println("file.exists():" + file.exists());
return file.exists();
}
//…………
//……省去的无关方法的代码………
//…………
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > use the set_fileDirectory(), set_byte() and
* checkIfFileExist(String fileDirectory) methods first < br >
* to set a righdis.readFully(b)t file directory and file content < br >
* before using this method; < br >
* < blockquote >
*/
public synchronized void DataInputFully() {
if (get_fileLocation() != null && get_fileName() != null
&& get_fileContent() != null && get_byte() != null) {
try {
FileOutputStream fos = new FileOutputStream(get_fileDirectory());
DataOutputStream dos = new DataOutputStream(fos);
dos.write(get_byte());
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println( "fileLocation:" + get_fileLocation()
+ "; or fileName:" + get_fileName() + "; or byte[]:"
+ get_byte() + " is null.");
}
}
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > please use set_fileDirectory() to set the file directory,
* and use checkIfFileExist(String fileDirectory) first < br >
* before using this method. < br >
* </ blockquote >
*
* @param b
* the _byte to set
*/
public void DataInputFully( byte[] b) {
set_byte(b);
DataInputFully();
}
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > create a file, whose directory as < code > fileDirectory </ code >
* and file content as < code > get_byte() </ code > . < br >
* Use checkIfFileExist(String fileDirectory) first < br >
* </ blockquote >
*
* @param fileDirectory
* the _fileDirectory to set < br >
* @param b
* the _byte to set, contains the content of file.
*/
public void DataInputFully(String fileDirectory, byte[] b) {
set_fileDirectory(fileDirectory);
set_byte(b);
DataInputFully();
}
/**
* input get_byte() to get_fileDirectory. If object file is exist, it will
* be replaced without warning. < br >
* < br >
* NOTE: < br >
* < blockquote > create file named < code > fileName </ code > in
* < code > fileLocation </ code > input < code > get_byte() </ code > to file named as
* < code > fileName </ code > in < code > fileLocation </ code > . < br >
* Use checkIfFileExist(String fileDirectory) first < br >
* </ blockquote >
*
* @param fileLocation
* the _fileLocation to set and will be used to set the
* _fileDirectory
* @param fileName
* the _fileName to set and will be used to set the
* _fileDirectory
* @param b
* the _byte to set and will be write to the file with
* _fileDirectory directory. _byte Contains the content of file.
*/
public void DataInputFully(String fileLocation, String fileName, byte[] b) {
set_fileDirectory(fileLocation, fileName);
set_byte(b);
DataInputFully();
}
/**
* Out put a file by using DataOutputStream class. < br >
* < br >
* NOTE: < br >
* < blockquote > use the set_fileDirectory() method first < br >
* to set a right file directory < br >
* before using this method; < br >
* </ blockquote >
*
* @return null:if fileDirectory is null; < br >
* file content byte[];
*/
public synchronized byte[] DataOutputFully() {
if (get_fileDirectory() != null) {
File file = new File(get_fileDirectory());
if (file.exists()) {
try {
FileInputStream fis;
fis = new FileInputStream(get_fileDirectory());
DataInputStream dis = new DataInputStream(fis);
byte[] b = new byte[dis.available()];
while (dis.available() > 0) {
dis.readFully(b);
// System.out.println(" :" + b.length);
}
set_byte(b);
String tmpStr = "";
for ( int i = 0; i < b.length; i++) {
tmpStr += String.valueOf(b[i]);
}
set_fileContent(tmpStr);
// System.out.println("\n" + get_fileContent() + "\n"
// + get_fileLocation() + "\n" + get_fileName());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return get_byte();
} else {
System.out.println( "fileDirectory:" + get_fileDirectory()
+ "; and the file is not exist.");
return null;
}
} else {
System.out.println( "fileDirectory:" + get_fileDirectory()
+ "; is null");
return null;
}
}
/**
* Out put a file, which directory as < code > fileDirectory </ code > , < br >
* by using DataOutputStream class. < br >
*
* @param fileDirectory
* the _fileDirectory to set and will be used to find the file,
* which is supposed to be opened. < br >
* @return byte[] _byte() the content of the chose file.
*/
public byte[] DataOutputFully(String fileDirectory) {
set_fileDirectory(fileDirectory);
return DataOutputFully();
}
/**
* Out put a file, which directory as < code > fileLocation </ code > plus
* < code > fileName </ code > , < br >
* by using DataOutputStream class. < br >
*
* @param fileLocation
* the _fileLocation to set and will be used to set the
* _fileDirectory
* @param fileName
* the _fileName to set and will be used to set the
* _fileDirectory
* @return byte[[] get_byte() the content of the chose file.Data
*/
public byte[] DataOutputFully(String fileLocation, String fileName) {
set_fileDirectory(fileLocation, fileName);
return DataOutputFully();
}
public static void main(String[] args) {
InputOutput io = new InputOutput();
io.set_fileDirectory( "/home/knowyourself1010/Tracker.class");
io.set_fileContent( "1234567890 abcdefg ABCDEFG 好的繁体字简体字复杂么?");
// io.DataInput();
System.out.println(io.DataOutput());
io.set_fileDirectory( "/home/knowyourself1010/file.class");
io.DataInput();
// io.set_fileContent("rfgadssssssssssssssdsaaaadwefewfefeferegrqedwdq");
// System.out.println(io.get_fileContent());
}
}
CopyUsefulClasses.java:
/**
*
*/
package com.wordpress.iwillaccess.tools;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import com.wordpress.iwillaccess.classes.global.InputOutput;
/**
* @author knowyourself1010
*
*/
public class CopyUsefulClasses {
// 文件拷贝
private static boolean copy(String sourceFileLocation,
String objectFileLocation, String fileName) {
try // must try and catch,otherwise will compile error
{
if (sourceFileLocation.substring(sourceFileLocation.length() - 1) != "/") {
sourceFileLocation += "/";
}
if ((objectFileLocation.substring(objectFileLocation.length() - 1)) != "/") {
objectFileLocation += "/";
}
InputOutput inputOutput = new InputOutput();
byte[] b = inputOutput
.DataOutputFully(sourceFileLocation, fileName);
inputOutput.DataInputFully(objectFileLocation, fileName, b);
return true; // if success then return true
} catch (Exception e) {
System.out.println( "Error!");
return false; // if fail then return false
}
}
// 读取路径,copy
private static int dealClass(String needfile, String sdir, String odir)
throws IOException {
int sn = 0; // 成功个数
if (odir.length() > 0 && sdir.length() > 0) {
if ((sdir.substring(sdir.length() - 1)) != "/") {
sdir += "/";
}
if (odir.substring(odir.length() - 1) != "/") {
odir += "/";
}
File usedclass = new File(needfile);
if (usedclass.canRead()) {
String line = null;
LineNumberReader reader = new LineNumberReader(
new InputStreamReader( new FileInputStream(usedclass),
"UTF-8"));
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.contains( ".") || line.contains( "/")) {
// format the direction from package name to path
String dir = line.replace( ".", "/");
// filter the file name.
String tmpdir = dir.substring( 0, dir.lastIndexOf( "/"));
String sourceFileLocation = sdir + tmpdir;
String objectFileLocation = odir + tmpdir;
String fileName = dir.substring(
dir.lastIndexOf( "/") + 1, dir.length())
+ ".class";
File fdir = new File(objectFileLocation);
if (!fdir.exists())
fdir.mkdirs();
boolean copy_ok = copy(sourceFileLocation,
objectFileLocation, fileName);
if (copy_ok)
sn++;
else {
System.out.println(line);
}
} else {
sn = - 1;
}
}
}
}
return sn;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
BufferedReader lineOfText = null;
// get need classes log file direction
System.out
.println( "needfile (file logged the full name of useful classes ):");
lineOfText = new BufferedReader( new InputStreamReader(System.in));
String needfile = lineOfText.readLine();
// get source folder direction
System.out
.println(needfile
+ " \n Source Folder Direction (the direction of the folder filled the classes need to be filtered.):");
lineOfText = new BufferedReader( new InputStreamReader(System.in));
String sdir = lineOfText.readLine();
// get object folder direction
System.out
.println(sdir
+ " \n Object Folder Direction (the direction of the folder used to fill the filtered classes.):");
lineOfText = new BufferedReader( new InputStreamReader(System.in));
String odir = lineOfText.readLine();
System.out.println(odir + " \n ");
int sn = dealClass(needfile, sdir, odir);
System.out.print(sn);
} catch (IOException e) {
// TODO 自动生成 catch 块
e.printStackTrace();
}
}
}
(在此感谢irc: ##java上朋友提示读写Binary文件的注意事项:不要用Reader方法!Char也不太支持哦。)
运行CopyUsefulClasses.java。首先输入usedClasses.txt的绝对路径,回车,在输入jre/lib/rt.jar解压後的rt文件夹所在的路径,回车,再输入ort(所要存放拷贝过来的有用的.class文件的文件夹)。然后等上几分中,期间会提示,你的产品程序所用到的jre不包含的类不存在,不用管,因为我们呢只拷贝rt文件中的.class文件。
最后將ort文件夹下面的所有文件加压缩为rt.zip文件,并改为rt.jar。
注意:1.是选中ort文件夹下所有子文件夹,而非选中ort文件夹,并压缩。
2.在Ubuntu10.10下如果选择压缩为jar格式文件,可能会少压缩进java.lang.Object.class等文件(估计是个bug),所以需要压缩为.zip再该类型为.jar。
最后,將要简化的jre中的rt.jar替换为这里压缩得到的rt.jar文件。我的只有2MB。
用 java -jar [您的jar程序路径]
来测试简化後的jre是否成功吧。