• 反编译之崩溃定位


    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.首先我们需要找崩溃所在的类和方法

    1.1普通混淆类

    既然路径是被混淆的,首先我们需要根据混淆的mapping文件来还原出崩溃路径。
    mapping文件一般的位置在

    /app/build/outputs/mapping/release/mapping.txt
    
    • 1

    根据mapping文件我们很容找到路径对应的类为NewLiveCartSkuViewHolder:
    根据混淆文件找到对应类
    然后根据崩溃信息我们就能找到类中对应的方法onBindViewHolder

    1.2匿名内部类混淆

    有时候,我们找到的类,前面对应的混淆前引用是这样的
    在这里插入图片描述
    这说明前面是一个匿名内部类,它存在于LiveSkunVIew当中,并且是第15个,因为匿名内部类一般没有名字,所以在编译成class文件的时候为了能给它一个索引,一般会用“外部的类$数字编号”来表示匿名内部类。那我们如何找到这个匿名内部类的声明在哪一行呢?我们可以往下找,我们可以找到下面有一个匿名内部类的初始化方法,void(com.jd.lib.mylive.view.widget.LiveSkinView):1754:1754 -> ,这方法表示类加器加载了这个匿名内部,并且在1754行加载的。这样的话,我们就可以定位到这个匿名内部类了。

    接下来我们需要分析一下崩溃的行数在哪一行。

    2.寻找崩溃的代码行数

    寻找崩溃的代码行数就没那么容易,也就是本文的重点-反编译。
    因为报错信息(SourceFile:169)给到的行数并不是真实代码所在的行数,而是编译混淆后class文件里面崩溃的行数。因此,若要定位到行数,我们必须先将apk进行反编译,然后将反编译后的dex转成jar,最后分析jar文件来定位崩溃的具体位置。

    2.1借用反编译工具jadx查看反编译后的内容

    这里我们推荐一个很好用的反编译开源工具jadx,路径如下

    https://github.com/skylot/jadx

    用这个工具我们只需要将apk,倒入即可看到反编译后的结果,不过有的方法和类可能反编译不出来
    jadx展示
    下面是反编译后的结果
    反编译后的结果
    首先我们根据混淆的路径来找到我们想要定位的类和方法的大致位置,然后我们借助右下角的code或者simple那一栏来进行问题的定位,如果code里面的方法没被反编译出来,我们可以尝试在simple那一栏里面找,我这里就遇到了clode栏没被反编译出来的情况,因此我从simple栏找到了对应的方法,如下图
    找到崩溃的方法
    最后我们只需要找到169行,即可找到崩溃具体的位置,这里我们需要注意一下左边的行数,一定要点击左侧tab并确定行数切换到了从方法开始计算行数的模式,因为崩溃信息中(SourceFile:169)169所指的行数表示的是从崩溃所在的方法开始计数的行数,且必须是源文件中的行数。由于jadx显示的是反编译过后的文件代码(目的是方便我们阅读),且它已经帮我们标记好了反编译前的行号,因此我们只需要在onBindViewHolder中找到反编译前的行号就能找到崩溃的位置。
    找到编译代码的行号
    如上图,我们找到了行号在169的位置,发现该行做了判断一个字段的长度,如果price为空,那么就会发生nullPointException,正好对应了上面的崩溃信息String.length()的空指针崩溃。
    最后们回归到源代码中找到了此行,
    源码验证代码
    问题得到验证。

  • 相关阅读:
    Ubuntu22.04 & Win11 双系统hibernate冷切换实现
    C++ 函数
    Elasticsearch插件开发之自定义搜索语法
    JVM虚拟机-虚拟机执行子系统-第6章 字节码指令
    TouchEffects - Android View点击特效
    Java之JDBC
    Blazor前后端框架Known-V1.2.3
    【C++ techniques】Reference counting(引用计数)
    第七章 解析PyTorch中Hook函数(工具)
    Acwing 802. 区间和
  • 原文地址:https://blog.csdn.net/StramChen/article/details/133182514