posts - 42,comments - 83,trackbacks - 0
       最近因为工作需要反编译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], nullnull);
 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 走走停停又三年 阅读(2205) 评论(1)  编辑  收藏 所属分类: FJin Dev

FeedBack:
# re: 基于Jad的批量反编译工具JarDecompiler
2009-09-16 08:21 | sorcerer
试了一下,好像都要执行2次才能反编译,一个200多k的jar也是这样,第一次建了unzip目录和class,还有decompile下的文件夹,但是没有反编译出类文件.  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: