最近因为工作需要反编译oracle的jdbc driver,用了frontend plus,发现无法编译整个jar,用起来比较繁琐。于是,狠狠心写了这个么个工具类,时间有限,没有什么设计思想,本着拿来就用的态度,很简陋的完成了这个小任务。 :) 基本思想是:能够编译指定目录下的所有jar文件,并将文件生成到指定的目录下,同时将所有的jad文件重名成java。
这个工具依赖于jad, 所以需要预先安装。执行后会在outputDir下生成两个目录: unzip, decompile。用法如下:JarDecompiler <jadPath> [targetDir] [outputDir], 如果需要自定义的一些功能,大家可以根据Jad的一些option进行修改。因为基于runtime exec,我自己使用过程中发现,如过jar过多、过大的话,运行一边以后,发现并不是所有的文件都能反编译出来,可能需要连续执行几次才能将所有jar包编译完成。这个问题比较怪异,谁有兴趣的话,可以看看。中间还有生成bat文件的代码,不过代码太多的话,显得比较乱,被我去掉了,有兴趣的可以留下邮箱。
1 package test.decompiler;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.util.jar.JarFile;
6 import java.util.jar.JarEntry;
7 import java.io.InputStream;
8 import java.io.FileOutputStream;
9 import java.io.DataOutputStream;
10 import java.util.ArrayList;
11
12
13 public class JarDecompiler {
14
15 private String jadPath = null;
16 private String targetDir = ".";
17 private String outputDir = ".";
18 private File unzipFile = null;
19 private static String UNZIP = "unzip";
20 private static String DECOMPILE="decompile";
21
22 private ArrayList jarFileList = null;
23 private ArrayList dirList = null;
24 private ArrayList fileList = null;
25
26
27 public JarDecompiler(String jadPath, String targetDir, String outputDir) {
28 // TODO Auto-generated constructor stub
29 this.jadPath = jadPath;
30 if(targetDir != null)
31 this.targetDir = targetDir;
32 if(outputDir != null)
33 this.outputDir = outputDir;
34 this.outputDir = this.outputDir + System.getProperty("file.separator");
35 jarFileList = new ArrayList();
36 dirList = new ArrayList();
37 fileList = new ArrayList();
38 }
39
40 /**
41 * @param args
42 */
43 public static void main(String[] args) {
44 // TODO Auto-generated method stub
45 JarDecompiler decompiler = null;
46 if((args.length < 1) || (args.length > 3))
47 {
48 usage();
49 System.exit(1);
50 }
51 else if(args.length ==1)
52 decompiler = new JarDecompiler(args[0], null, null);
53 else if(args.length ==2)
54 decompiler = new JarDecompiler(args[0], args[1], null);
55 else if(args.length ==3)
56 decompiler = new JarDecompiler(args[0], args[1], args[2]);
57 decompiler.run();
58 }
59
60 public void run()
61 {
62 if(initializeFiles())
63 {
64 getJarFileNameList(targetDir);
65 //printArrayList(jarFileList);
66 for(int loop=0; loop<jarFileList.size(); loop++)
67 {
68 unzipJar((String)jarFileList.get(loop));
69 }
70 getDirNameList(outputDir + UNZIP);
71 //printArrayList(dirList);
72 checkDir(outputDir + DECOMPILE);
73 String dirName= null;
74 for(int i=0; i<dirList.size(); i++)
75 {
76 dirName = (String)dirList.get(i);
77 dirName = dirName.replaceFirst(UNZIP, DECOMPILE);
78 checkDir(dirName);
79 }
80 decompile();
81 getFileNameList(outputDir + DECOMPILE);
82 //printArrayList(fileList);
83 renameFiles();
84 //printJarFiles();
85 unzipFile.delete();
86 }
87 }
88
89 private void printArrayList(ArrayList list)
90 {
91 for(int loop=0; loop<list.size(); loop++)
92 {
93 System.out.println(list.get(loop));
94 }
95 }
96
97 private boolean initializeFiles()
98 {
99 boolean ret = true;
100 unzipFile = new File(outputDir + UNZIP);
101
102 if(unzipFile.exists())
103 {
104 //ret = false;
105 System.out.println(UNZIP + " has been existed in " + outputDir);
106 }else
107 {
108 try
109 {
110 unzipFile.mkdir();
111 }catch(Exception e)
112 {
113 e.printStackTrace();
114 }
115 }
116 return ret;
117 }
118
119 private void getJarFileNameList(String targetDir)
120 {
121 File[] files = null;
122 File target = new File(targetDir);
123 if(target.exists() && target.isDirectory())
124 {
125 files = target.listFiles();
126 for(int loop=0; loop<files.length; loop++)
127 {
128 if(files[loop].isFile() && files[loop].getName().endsWith(".jar"))
129 {
130 jarFileList.add(files[loop].getAbsolutePath());
131 }else if(files[loop].isDirectory())
132 {
133 getJarFileNameList(files[loop].getAbsolutePath());
134 }
135 }
136 }
137 }
138
139 private void getDirNameList(String dirName)
140 {
141 File[] files = null;
142 File target = new File(dirName);
143 if(target.exists() && target.isDirectory())
144 {
145 files = target.listFiles();
146 for(int loop=0; loop<files.length; loop++)
147 {
148 if(files[loop].isDirectory())
149 {
150 dirList.add(files[loop].getAbsolutePath());
151 getDirNameList(files[loop].getAbsolutePath());
152 }
153 }
154 }
155 }
156
157 private void getFileNameList(String dirName)
158 {
159 File[] files = null;
160 File target = new File(dirName);
161 if(target.exists() && target.isDirectory())
162 {
163 files = target.listFiles();
164 for(int loop=0; loop<files.length; loop++)
165 {
166 if(files[loop].isDirectory())
167 {
168 getFileNameList(files[loop].getAbsolutePath());
169 }else if(files[loop].isFile())
170 {
171 fileList.add(files[loop].getAbsolutePath());
172 }
173 }
174 }
175 }
176
177 private boolean unzipJar(String fileName)
178 {
179 boolean ret = true;
180 String postfixName = fileName.substring(outputDir.length());
181 String zipTo = outputDir + UNZIP + System.getProperty("file.separator");
182
183 Object[] dirs = getDirs(postfixName).toArray();
184
185 checkDir(zipTo);
186 for(int loop=0; loop<dirs.length; loop++)
187 {
188 zipTo = zipTo + (String)dirs[loop];
189 if(zipTo.endsWith(".jar"))
190 {
191 zipTo.substring(0, zipTo.length() -4);
192 }
193 zipTo = zipTo + System.getProperty("file.separator");
194 checkDir(zipTo);
195 }
196
197 try
198 {
199 String cmd = "unzip -d " + zipTo + " " + fileName;
200 Runtime.getRuntime().exec(cmd);
201 }catch(IOException ioe)
202 {
203 ioe.printStackTrace();
204 }
205
206 return ret;
207 }
208
209 public void decompile()
210 {
211
212 String target = null;
213 String output = null;
214 String decopCmd = null;
215 InputStream es = null;
216
217 Process decompP = null;
218 int result = -1;
219 byte[] toRead = new byte[2048];
220 for(int i=0; i<dirList.size(); i++)
221 {
222 target = (String)dirList.get(i);
223 output = target;
224 output = output.replaceFirst(UNZIP, DECOMPILE);
225 decopCmd = "jad -ff -d " + output + " " + target +
226 System.getProperty("file.separator") + "*.class";
227 decopCmd = jadPath + System.getProperty("file.separator") + decopCmd;
228
229 //System.out.println(decopCmd);
230 try
231 {
232 decompP = Runtime.getRuntime().exec(decopCmd);
233 es = decompP.getErrorStream();
234 /*
235 while(es.read(toRead) > 0)
236 {
237 System.out.println(new String(toRead));
238 }
239 */
240 }catch(Exception e)
241 {
242 e.printStackTrace();
243 }
244 }
245 }
246
247
248 private void renameFiles()
249 {
250 String target = null;
251 String output = null;
252 String renameCmd = null;
253 File targetFile = null;
254 File destFile = null;
255 Process p = null;
256
257 for(int i=0; i<fileList.size(); i++)
258 {
259 if(((String)fileList.get(i)).endsWith(".jad"))
260 {
261 target = (String)fileList.get(i);
262 output = target;
263 output = output.replaceFirst(UNZIP, DECOMPILE);
264
265 targetFile = new File(output);
266 //System.out.println("rename from: " + output + " to: " + output.substring(0, output.length() -4) + ".java");
267 destFile = new File(output.substring(0, output.length() -4) + ".java");
268 targetFile.renameTo(destFile);
269 targetFile.delete();
270 try
271 {
272 Thread.currentThread().sleep(100);
273 }catch(Exception e)
274 {
275 e.printStackTrace();
276 }
277
278 /*
279 renameCmd = "cmd /c ren " + output + " " + output.substring(0, output.length() -4) + ".java";
280 System.out.println(renameCmd);
281 try
282 {
283 p = Runtime.getRuntime().exec(renameCmd);
284 p.waitFor();
285 }catch(Exception e)
286 {
287 e.printStackTrace();
288 }
289 */
290
291 }
292 targetFile = null;
293 destFile = null;
294 }
295 }
296
297 private void checkDir(String name)
298 {
299 File file = new File(name);
300 if(!file.exists())
301 {
302 file.mkdir();
303 }
304 }
305
306 public ArrayList getDirs(String name)
307 {
308 ArrayList list = new ArrayList();
309 while(name.indexOf(System.getProperty("file.separator")) != -1)
310 {
311 list.add(name.substring(0, name.indexOf(System.getProperty("file.separator"))));
312 name = name.substring(name.indexOf( System.getProperty("file.separator"))+1);
313 }
314
315 list.add(name.substring(0, name.length()-4));
316 return list;
317 }
318
319 private static void usage()
320 {
321 System.out.println("usage: java test.decompiler.JarDecompiler <Jad Path> [target Dir] [output Dir]");
322 }
323
324 }
325
posted on 2008-09-11 18:26
走走停停又三年 阅读(2200)
评论(1) 编辑 收藏 所属分类:
FJin Dev