基于Jad的批量反编译工具JarDecompiler
最近因为工作需要反编译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
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