反编译之崩溃定位
- 1.背景
- 问题定位
- 1.首先我们需要找崩溃所在的类和方法
- 2.寻找崩溃的代码行数
- 2.1借用反编译工具jadx查看反编译后的内容
1.背景
线上出了个崩溃(量挺大😭),但是apk是被混淆过的,一时摸不着头脑。崩溃信息如下:
主要就是一个再常见不过的空指针的崩溃,
—java.lang.NullPointerException: Attempt to invoke virtual method ‘int java.lang.String.length()’ on a null object reference
若要定位代码所在位置,主要就是看com.jd.lib.mylive.e.d.s.onBindViewHolder(SourceFile:169)这一行,这就是我们崩溃的最终地方,但是路径被混淆了,而且代码行位置也看不出任何信息。这就让我们很头大了,如何才能找到最终的代码报错位置呢?
问题定位
这里我们分两步定位,第一步是找到崩溃的类和方法,第二是找到崩溃的代码行数。
1.首先我们需要找崩溃所在的类和方法
既然路径是被混淆的,首先我们需要根据混淆的mapping文件来还原出崩溃路径。
mapping文件一般的位置在
/app/build/outputs/mapping/release/mapping.txt
根据mapping文件我们很容找到路径对应的类为NewLiveCartSkuViewHolder:
接下来我们需要分析一下崩溃的行数在哪一行。
2.寻找崩溃的代码行数
寻找崩溃的代码行数就没那么容易,也就是本文的重点-反编译。
因为报错信息(SourceFile:169)给到的行数并不是真实代码所在的行数,而是编译混淆后class文件里面崩溃的行数。因此,若要定位到行数,我们必须先将apk进行反编译,然后将反编译后的dex转成jar,最后分析jar文件来定位崩溃的具体位置。
2.1借用反编译工具jadx查看反编译后的内容
这里我们推荐一个很好用的反编译开源工具jadx,路径如下
https://github.com/skylot/jadx
用这个工具我们只需要将apk,倒入即可看到反编译后的结果,不过有的方法和类可能反编译不出来
下面是反编译后的结果
首先我们根据混淆的路径来找到我们想要定位的类和方法的大致位置,然后我们借助右下角的code或者simple那一栏来进行问题的定位,如果code里面的方法没被反编译出来,我们可以尝试在simple那一栏里面找,我这里就遇到了clode栏没被反编译出来的情况,因此我从simple栏找到了对应的方法,如下图
最后我们只需要找到169行,即可找到崩溃具体的位置,这里我们需要注意一下左边的行数,一定要点击左侧tab并确定行数切换到了从方法开始计算行数的模式,因为崩溃信息中(SourceFile:169)169所指的行数表示的是从崩溃所在的方法开始计数的行数,且必须是源文件中的行数。由于jadx显示的是反编译过后的文件代码(目的是方便我们阅读),且它已经帮我们标记好了反编译前的行号,因此我们只需要在onBindViewHolder中找到反编译前的行号就能找到崩溃的位置。
如上图,我们找到了行号在169的位置,发现该行做了判断一个字段的长度,如果price为空,那么就会发生nullPointException,正好对应了上面的崩溃信息String.length()的空指针崩溃。
最后们回归到源代码中找到了此行,
问题得到验证。