非原生 ROM 的 Crash 问题通用排查方法

栏目: Android · 发布时间: 5年前

内容简介:日常 Crash 治理过程中,经常会遇到一些比较难排查的问题,比如,Crash 堆栈信息中出现了一些本不应该出现的函数,这些函数其实是手机厂商修改了 Google 的原生 ROM,自己添加进去的。本文介绍了一种定位和排查非原生 ROM 的 Crash 问题的通用方法。日常清理 Crash 时,遇到一些空指针异常的问题,每天不多,但是日积月累,数量并不少,堆栈信息如下:翻看 android.os.Message 的源代码,并没有 toStringLite() 这个函数,显然,这是手机厂商修改了原生 ROM,自

日常 Crash 治理过程中,经常会遇到一些比较难排查的问题,比如,Crash 堆栈信息中出现了一些本不应该出现的函数,这些函数其实是手机厂商修改了 Google 的原生 ROM,自己添加进去的。本文介绍了一种定位和排查非原生 ROM 的 Crash 问题的通用方法。

问题的提出

日常清理 Crash 时,遇到一些空指针异常的问题,每天不多,但是日积月累,数量并不少,堆栈信息如下:

java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
	at android.os.Message.toStringLite(Message.java:507)
	at android.os.Looper.loop(Looper.java:221)
	at android.app.ActivityThread.main(ActivityThread.java:5809)
	at java.lang.reflect.Method.invoke(Native Method)
	at java.lang.reflect.Method.invoke(Method.java:372)
	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1113)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:879)

翻看 android.os.Message 的源代码,并没有 toStringLite() 这个函数,显然,这是手机厂商修改了原生 ROM,自己加上的。如何跟进此类适配性问题呢?

思考

此类 ROM 相关问题无法修复,只能从 App 的代码调用端进行适配,类似 H5 页面适配各种浏览器一样。所以,主要问题在于找出非原生 ROM 的执行逻辑,从而想办法避免 Crash。那么,如何发掘里面的执行逻辑呢?

探索

初步考虑,通过 ClassLoader 动态导出具体的 class 类,代码如下:

public class Demo {
    public static void main(String[] args) {
        try {
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            InputStream inputStream = classLoader.getResourceAsStream("java/util/List.class");
            FileOutputStream fileOutputStream = new FileOutputStream("List.class");
            byte[] buffer = new byte[1024];
            int length;
            while ((length = inputStream.read(buffer)) > 0) {
                fileOutputStream.write(buffer, 0, length);
            }
            fileOutputStream.close();
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这种方法对 Java 是适用的,但是在 Android 中并不适用。

通用方法

既然动态方法不行,考虑静态方法,毕竟在手机 ROM 中,必然有对应的文件。

步骤一

首先,通过 Crash 平台的附加信息,找到手机的型号、版本「型号:OPPO R9tm,版本:5.1」,找一台同型号、同版本的手机「美团有云真机平台,上面的手机种类繁多」,连上 adb。

步骤二

把 boot.oat 文件从手机 pull 下来,boot.oat 包含启动相关的代码,可理解为里面有优化过的 framework.jar 文件,对应 SDK 的 android.jar 文件,文件较大,有 85M 左右。

[leidiqiu@leidiqiu: ] ~/Desktop $ adb -s 172.18.92.198:44429 pull /system/framework/arm64/boot.oat .
/system/framework/arm64/boot.oat: 1 file pulled. 0.4 MB/s (85477748 bytes in 229.612s)
[leidiqiu@leidiqiu: ] ~/Desktop $ ls -l boot.oat 
-rw-r--r--  1 leidiqiu  staff  85477748 May  8 16:17 boot.oat

步骤三

下载 oat2dex.jar 工具,并将 oat 文件转换成 dex 文件,会生成 odex、dex 两个文件夹。

[leidiqiu@leidiqiu: ] ~/Desktop $ java -jar ~/libs/oat2dex.jar boot boot.oat 
05-08 16:23:27:465 Output raw dex: /Users/leidiqiu/Desktop/odex/core-libart.dex
05-08 16:23:27:466 Output raw dex: /Users/leidiqiu/Desktop/odex/conscrypt.dex
05-08 16:23:27:467 Output raw dex: /Users/leidiqiu/Desktop/odex/okhttp.dex
05-08 16:23:27:467 Output raw dex: /Users/leidiqiu/Desktop/odex/core-junit.dex
05-08 16:23:27:469 Output raw dex: /Users/leidiqiu/Desktop/odex/bouncycastle.dex
05-08 16:23:27:472 Output raw dex: /Users/leidiqiu/Desktop/odex/ext.dex
05-08 16:23:27:488 Output raw dex: /Users/leidiqiu/Desktop/odex/framework.dex
05-08 16:23:27:503 Output raw dex: /Users/leidiqiu/Desktop/odex/framework-classes2.dex
05-08 16:23:27:511 Output raw dex: /Users/leidiqiu/Desktop/odex/telephony-common.dex
05-08 16:23:27:512 Output raw dex: /Users/leidiqiu/Desktop/odex/voip-common.dex
05-08 16:23:27:516 Output raw dex: /Users/leidiqiu/Desktop/odex/ims-common.dex
05-08 16:23:27:516 Output raw dex: /Users/leidiqiu/Desktop/odex/mms-common.dex
05-08 16:23:27:517 Output raw dex: /Users/leidiqiu/Desktop/odex/android.policy.dex
05-08 16:23:27:523 Output raw dex: /Users/leidiqiu/Desktop/odex/apache-xml.dex
05-08 16:23:27:529 Output raw dex: /Users/leidiqiu/Desktop/odex/oppo-framework.dex
05-08 16:23:27:530 Output raw dex: /Users/leidiqiu/Desktop/odex/mediatek-common.dex
05-08 16:23:27:531 Output raw dex: /Users/leidiqiu/Desktop/odex/mediatek-framework.dex
05-08 16:23:27:532 Output raw dex: /Users/leidiqiu/Desktop/odex/mediatek-telephony-common.dex
05-08 16:23:27:786 De-optimizing /system/framework/core-libart.jar
05-08 16:23:30:094 Output to /Users/leidiqiu/Desktop/dex/core-libart.dex
05-08 16:23:30:094 De-optimizing /system/framework/conscrypt.jar
05-08 16:23:30:208 Output to /Users/leidiqiu/Desktop/dex/conscrypt.dex
05-08 16:23:30:208 De-optimizing /system/framework/okhttp.jar
05-08 16:23:30:356 Output to /Users/leidiqiu/Desktop/dex/okhttp.dex
05-08 16:23:30:356 De-optimizing /system/framework/core-junit.jar
05-08 16:23:30:371 Output to /Users/leidiqiu/Desktop/dex/core-junit.dex
05-08 16:23:30:371 De-optimizing /system/framework/bouncycastle.jar
05-08 16:23:30:928 Output to /Users/leidiqiu/Desktop/dex/bouncycastle.dex
05-08 16:23:30:928 De-optimizing /system/framework/ext.jar
05-08 16:23:31:483 Output to /Users/leidiqiu/Desktop/dex/ext.dex
05-08 16:23:31:483 De-optimizing /system/framework/framework.jar
05-08 16:23:36:301 Output to /Users/leidiqiu/Desktop/dex/framework.dex
05-08 16:23:36:301 De-optimizing /system/framework/framework.jar:classes2.dex
05-08 16:23:38:611 Output to /Users/leidiqiu/Desktop/dex/framework-classes2.dex
05-08 16:23:38:611 De-optimizing /system/framework/telephony-common.jar
05-08 16:23:40:395 Output to /Users/leidiqiu/Desktop/dex/telephony-common.dex
05-08 16:23:40:395 De-optimizing /system/framework/voip-common.jar
05-08 16:23:40:440 Output to /Users/leidiqiu/Desktop/dex/voip-common.dex
05-08 16:23:40:440 De-optimizing /system/framework/ims-common.jar
05-08 16:23:40:625 Output to /Users/leidiqiu/Desktop/dex/ims-common.dex
05-08 16:23:40:625 De-optimizing /system/framework/mms-common.jar
05-08 16:23:40:626 Output to /Users/leidiqiu/Desktop/dex/mms-common.dex
05-08 16:23:40:626 De-optimizing /system/framework/android.policy.jar
05-08 16:23:40:764 Output to /Users/leidiqiu/Desktop/dex/android.policy.dex
05-08 16:23:40:764 De-optimizing /system/framework/apache-xml.jar
05-08 16:23:41:178 Output to /Users/leidiqiu/Desktop/dex/apache-xml.dex
05-08 16:23:41:178 De-optimizing /system/framework/oppo-framework.jar
05-08 16:23:41:613 Output to /Users/leidiqiu/Desktop/dex/oppo-framework.dex
05-08 16:23:41:613 De-optimizing /system/framework/mediatek-common.jar
05-08 16:23:41:660 Output to /Users/leidiqiu/Desktop/dex/mediatek-common.dex
05-08 16:23:41:660 De-optimizing /system/framework/mediatek-framework.jar
05-08 16:23:41:889 Output to /Users/leidiqiu/Desktop/dex/mediatek-framework.dex
05-08 16:23:41:889 De-optimizing /system/framework/mediatek-telephony-common.jar
05-08 16:23:41:891 Output to /Users/leidiqiu/Desktop/dex/mediatek-telephony-common.dex

步骤四

查看 dex 文件夹,发现有 framework.dex 文件。

[leidiqiu@leidiqiu: ] ~/Desktop $ cd dex/
[leidiqiu@leidiqiu: ] ~/Desktop/dex $ ls
android.policy.dex            ext.dex                       mediatek-telephony-common.dex
apache-xml.dex                framework-classes2.dex        mms-common.dex
bouncycastle.dex              framework.dex                 okhttp.dex
conscrypt.dex                 ims-common.dex                oppo-framework.dex
core-junit.dex                mediatek-common.dex           telephony-common.dex
core-libart.dex               mediatek-framework.dex        voip-common.dex

步骤五

下载 dex2jar-2.0.zip 工具,将 dex 转成 jar,并用 JD-GUI 打开,JD-GUI 下载地址: http://java-decompiler.github.io/。

[leidiqiu@leidiqiu: ] ~/Desktop/dex $ dex2jar.sh framework.dex 
dex2jar framework.dex -> ./framework-dex2jar.jar
Detail Error Information in File ./framework-error.zip
Please report this file to http://code.google.com/p/dex2jar/issues/entry if possible.
[leidiqiu@leidiqiu: ] ~/Desktop/dex $ open framework-dex2jar.jar -a JD-GUI.app

步骤六

通过 JD-GUI 查看,终于找到了 Message 类,里面确实有 toStringLite() 方法。

非原生 ROM 的 Crash 问题通用排查方法

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

实战Linux编程精髓

实战Linux编程精髓

罗宾斯 / 中国电力出版社 / 2005-7 / 59.80元

编写应用软件,特别是那些比较重要的软件,毫无疑问要涉及到系统调用。在UNIX/Linux环境下编程更是如此。要想编写优秀的软件,就必须熟悉这些系统调用的方方面面。通过阅读这本书,你能够快速地掌握这些重要技术,以构建严谨的Linux软件。全书主要分为三大部分:第一部分讨论了基本的编程问题,包括Linux编程环境、基本的文件和进程管理与操作、内存操作,还介绍了一些基本的库接口。第二部分比较深入地讨论了......一起来看看 《实战Linux编程精髓》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具