通常我们的代码都是通过ProGuard进程混淆的,混淆后每次修改编译后在proguard文件夹下会生成下列文件:
dump.txt:
描述.apk文件中所有类文件的内部结构
mapping.txt:
列出原始类的方法、字段与混淆后的代码间的映射,这个文件比较重要,如果你的代码混淆后会产生bug的话,log提示中是混淆后的代码,希望定位到源代码的话就可以根据mapping.txt反推。
sends.txt:
列出了未被混淆的类和成员
usage.txt
列出了在apk中删除的代码
ReTrace是ProGuard的“去混淆”堆栈跟踪的配套工具,ReTrace可以读取一个混淆的堆栈信息,并将其恢复到没有混淆的情况。恢复基于ProGuard在混淆过程中可以写出的映射文件mapping.txt。映射文件将原始类名和类成员名称链接到其混淆名称,它被放在/tools/proguard/lib/目录下,大致工作流程如下图:
运行的语法为:
java -jar retrace.jar [options...] mapping_file [stacktrace_file]mapping_file
混淆时生成的映射文件的名称,
stacktrace_file
指定包含堆栈跟踪的文件的名称
options:支持以下选项:
-verbose
指定打印更多信息丰富的堆栈跟踪,不仅包括方法名称,还包括方法返回类型和参数,以及方法的行号等信息,这个对于快速定位问题帮很有帮助,当然它得有个前期就是你在配置混淆的时候,保留行号信息 -keepattributesSourceFile,LineNumberTable。
-regex regular_expression
指定用于解析堆栈跟踪中的行的正则表达式。指定一个不同的正则表达式允许去除模糊更多的一般类型的输入,而不仅仅是堆栈跟踪。默认值适用于大多数JVM产生的堆栈跟踪:
现在假设处理后的应用程序抛出异常:
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
at proguard.y.a(MyApplication:188)
at proguard.y.a(MyApplication:158)
at proguard.y.a(MyApplication:136)
at proguard.y.a(MyApplication:66)
at proguard.ProGuard.c(MyApplication:218)
at proguard.ProGuard.a(MyApplication:82)
at proguard.ProGuard.main(MyApplication:538)
Caused by: java.io.IOException: No such file or directory
at proguard.d.q.a(MyApplication:50)
at proguard.y.a(MyApplication:184)
... 6 more如果我们将堆栈跟踪保存在文件中stacktrace.txt,我们可以使用以下命令恢复堆栈跟踪:
java -jar retrace.jar mapping.txt stacktrace.txt
输出将对应于原始堆栈跟踪:
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
at proguard.InputReader.readInput(InputReader.java:188)
at proguard.InputReader.readInput(InputReader.java:158)
at proguard.InputReader.readInput(InputReader.java:136)
at proguard.InputReader.execute(InputReader.java:66)
at proguard.ProGuard.readInput(ProGuard.java:218)
at proguard.ProGuard.execute(ProGuard.java:82)
at proguard.ProGuard.main(ProGuard.java:538)
Caused by: java.io.IOException: No such file or directory
at proguard.io.DirectoryPump.pumpDataEntries(DirectoryPump.java:50)
at proguard.InputReader.readInput(InputReader.java:184)
... 6 more使用行号恢复堆栈跟踪(详细)
在前面的例子中,我们也可以使用verbose标志:
java -jar retrace.jar -verbose mapping.txt stacktrace.txt
输出结果将如下所示:
java.io.IOException: Can't read [dummy.jar] (No such file or directory)
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPathEntry,proguard.io.DataEntryReader)(InputReader.java:188)
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPath,int,int,proguard.io.DataEntryReader)(InputReader.java:158)
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPath,proguard.io.DataEntryReader)(InputReader.java:136)
at proguard.InputReader.void execute(proguard.classfile.ClassPool,proguard.classfile.ClassPool)(InputReader.java:66)
at proguard.ProGuard.void readInput()(ProGuard.java:218)
at proguard.ProGuard.void execute()(ProGuard.java:82)
at proguard.ProGuard.void main(java.lang.String[])(ProGuard.java:538)
Caused by: java.io.IOException: No such file or directory
at proguard.io.DirectoryPump.void pumpDataEntries(proguard.io.DataEntryReader)(DirectoryPump.java:50)
at proguard.InputReader.void readInput(java.lang.String,proguard.ClassPathEntry,proguard.io.DataEntryReader)(InputReader.java:184)
... 6 more我们还可以在直接在程序中使用代码调用,我们只要将retrace.jar引入我们的工程,就可以愉快的使用了,直接来看代码:
public static void ReTrace(String mapFile,String crashFile,String outFile) {
try {
File file = new File(outFile);
FileOutputStream fis = new FileOutputStream(file, false);
PrintStream out = new PrintStream(fis);
//这个重定向我们的输出到指定的位置
System.setOut(out);
proguard.retrace.ReTrace localReTrace = new proguard.retrace.ReTrace(proguard.retrace.ReTrace.STACK_TRACE_EXPRESSION,
true, new File(mapFile), new File(
crashFile));
localReTrace.execute();
out.close();
fis.close();
} catch (IOException e) {
System.out.println("转码失败");
e.printStackTrace();
}
}通过调用它的ReTrace(String mapFile,String crashFile,String outFile)方法,
第一个参数为mapping文件路径地址
第二个参数为我们的堆栈信息文件地址
第三个文件是我们要输出解混淆后的文件地址
参考信息www.guardsquare.com/en/proguard…