首页 > 代码库 > 统计JAR包DEX文件中的方法数目

统计JAR包DEX文件中的方法数目

    前段时间做Android项目中,一直出现方法数超过65535的问题,如果混淆后代码中的方法数目没有超过65535,可以通过

在project.properties文件中加上一行dex.force.jumbo=true,解决这个问题。

  后来自己参考了网上的一些方法,写了个小工具用来统计JAR包和DEX文件中的方法数目。主要原理就是利用DEX的文件结构的文件头中有个method_ids_siz来统计方法数目。

现在分享出来,代码如下,直接拷贝编译成JAR包,然后控制台:java -jar XXX.jar file 就可以看到输出结果了。目前支持文件夹、JAR和DEX文件。

import java.io.BufferedInputStream;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStreamReader;public class Test2 {	private void test() {	}	private final static String JAR = "jar";	private final static String DEX = "dex";	private final static String DIR = "dir";	private final static String UNKNOWN = "unknown";	/**	 * 根据扩展名获取文件类型	 */	public static String getFileType(String path) {		String type = UNKNOWN;		try {			File file = new File(path);			if (file.isDirectory()) {				type = DIR;			} else {				if (getExtensionName(file.getName()).equalsIgnoreCase(DEX)) {					type = DEX;				} else if (getExtensionName(file.getName()).equalsIgnoreCase(						JAR)) {					type = JAR;				}			}		} catch (Exception e) {		}		return type;	}	public static void main(String[] args) {		if (args.length != 1) {			System.out.println("Param Error");		} else {			String type = getFileType(args[0]);			if (type.equalsIgnoreCase(DEX)) {				resolveDex(args[0]);			} else if (type.equalsIgnoreCase(JAR)) {				resolveJar(args[0]);			} else if (type.equalsIgnoreCase(DIR)) {				resolveDir(args[0]);			} else {				System.err.println("Unknown File Type");			}		}		System.out.println("解析结束");	}	/**	 * 简单的获取扩展名,不完全准确。完全准确的话,可以根据文件流判断。	 * @param filename	 * @return	 */	public static String getExtensionName(String filename) {		if ((filename != null) && (filename.length() > 0)) {			int dot = filename.lastIndexOf(‘.‘);			if ((dot > -1) && (dot < (filename.length() - 1))) {				return filename.substring(dot + 1);			}		}		return filename;	}	/**	 * 处理dex文件	 * 	 * @param path	 */	public static void resolveDex(String path) {		try {			File file = new File(path);			FileInputStream fis = new FileInputStream(file);			byte[] bytes = new byte[1000];			if (fis.read(bytes) != -1) {				StringBuilder sb = new StringBuilder();				for (int i = 91; i > 87; i--) {					sb.append(Integer.toBinaryString(bytes[i] & 255));				}				System.out.println(file.getName() + " 方法数目 : "						+ Integer.parseInt(sb.toString(), 2));			}		} catch (FileNotFoundException e) {			e.printStackTrace();		} catch (IOException e) {			e.printStackTrace();		}	}	/**	 * 解析JAR	 * 	 * @param path	 */	public static void resolveJar(String filePath) {		try {			String path = System.getenv("dx");			ProcessBuilder pb=new ProcessBuilder("dx.bat","--dex","--output=C://temp.dex",filePath);			pb.directory(new File(path));			pb.redirectErrorStream(true);			Process p =pb.start();			BufferedInputStream in = new BufferedInputStream(p.getInputStream());			BufferedReader inBr = new BufferedReader(new InputStreamReader(in));			String lineStr;						while ((lineStr = inBr.readLine()) != null) {				// 获得命令执行后在控制台的输出信息//					System.out.println(lineStr);// 打印输出信息			}					// 检查命令是否执行失败。			if (p.waitFor() != 0) {				if (p.exitValue() != 0){// p.exitValue()==0表示正常结束,1:非正常结束					System.err.println(filePath+" 命令执行失败!");					inBr.close();					in.close();					return;				}			}			inBr.close();			in.close();						File originFile = new File(filePath);			File file = new File("C://temp.dex");			FileInputStream fis = new FileInputStream(file);			byte[] bytes = new byte[1000];			if (fis.read(bytes) != -1) {				StringBuilder sb = new StringBuilder();				for (int i = 91; i > 87; i--) {					sb.append(String.format("%02x",(bytes[i] & 255)));				}				System.out.println(originFile.getAbsolutePath() + " 方法数目 : "						+ Integer.parseInt(sb.toString(), 16));			}			file.deleteOnExit();		} catch (IOException e) {			e.printStackTrace();		} catch (InterruptedException e) {			e.printStackTrace();		}	}		/**	 * 递归处理文件目录	 * @param path	 */	public static void resolveDir(String path){				File file=new File(path);		File[] fileList = file.listFiles();		for(int i = 0 ; i < fileList.length ; i++){			if(fileList[i].isDirectory()){				resolveDir(fileList[i].getAbsolutePath());			}else{				if(getFileType(fileList[i].getAbsolutePath()).equalsIgnoreCase(DEX)){					resolveDex(fileList[i].getAbsolutePath());				}else if(getFileType(fileList[i].getAbsolutePath()).equalsIgnoreCase(JAR)){					resolveJar(fileList[i].getAbsolutePath());				}							}					}	}}

  

统计JAR包DEX文件中的方法数目