如何使用 Android Developer Console 崩溃报告查找崩溃源?
How to find crash source using Android Developer Console crash report?
自从我在 Google Play 商店中发布了我的应用程序的新版本后,我在 Android 开发者控制台中收到了崩溃报告。
我在发布新版本后立即上传了 ProGuard mappings.txt
。因此所有日志都未混淆(所有class名称和方法都以明文形式出现)。不过我还是不太确定要不要看。
主要存在三个问题:
- 报告只显示崩溃方法,没有行号。所以我不知道是哪个方法导致了崩溃。
- 一些崩溃报告显示了使用
OR
的不同方法。这是什么意思?
- 并非所有报告都经过去混淆处理。有些仍然显示为匿名 class 和方法名称
示例:
// Crash Log with is NOT obfuscated
Caused by: java.lang.NullPointerException:
1: at com.example.MyApp.Path.To.Package.MyClass.myMethod1 (MyClass.java) // <-- No Line Numbers...
or .myMethod2 (MyClass.java) // <-- WHAT does this OR mean???
or .myMethod3 (MyClass.java)
2: at com.example.MyApp.Path.To.Package.MyClass.onCreateView (MyClass.java)
3: at android.support.v4.app.Fragment.performCreateView (Fragment.java)
4: at android.support.v4.app.FragmentManagerImpl.access0 (FragmentManagerImpl.java)
or .access0 (FragmentManagerImpl.java)
or .addFragment (FragmentManagerImpl.java)
or .allocBackStackIndex (FragmentManagerImpl.java)
or .animateRemoveFragment (FragmentManagerImpl.java)
...
5: at android.support.v4.app.FragmentManagerImpl.access0 (FragmentManagerImpl.java)
...
// Other crash seems to show the same problem but is still obfuscated
Caused by: java.lang.NullPointerException:
1: at com.example.MyApp.Path.To.Package.MyClass.a (MyClass.java:89) // <-- Line numbers available here...
2: at com.example.MyApp.Path.To.Package.MyClass.b (MyClass.java:40)
3: at android.support.v4.app.Fragment.performCreateView (Fragment.java)
... // Same call stack as above
问题:
- 为什么有些日志被反混淆,而其他(似乎显示相同的错误)却没有?上传映射文件后创建的两个日志。没有映射文件的旧版本日志显示明确的 "logs are obfuscated" 消息
- 调用堆栈中的
OR
语句是什么意思?这是否意味着这些方法中的每一个都发生了异常(这怎么可能)?
- 为什么去混淆后的日志中没有行号?给定的方法很长,没有任何进一步的信息,我不知道到底是什么导致了这个问题。混淆中的行号似乎指向随机行,这些行未以任何方式链接到真实代码。
所以主要问题是:
如何利用日志中的信息查找崩溃的根源?
最好改用 Fabrics。它将给出崩溃报告和行号。
您需要将以下选项添加到 Proguard 配置中:
# This option forces Proguard to use different obfuscated names
# for different members. It avoids the 'or' stack traces.
-useuniqueclassmembernames
# These options produce useful stacktraces preserving line numbers
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
如果没有 -useuniqueclassmembernames
,Proguard 可以为同一 class 中的不同方法分配相同的混淆名称(您可以在 mapping.txt 文件中看到它)。这就是为什么堆栈跟踪知道错误发生在方法 A 或方法 B 中 ,但不知道具体是哪一个。
使用 -useuniqueclassmembernames
选项,所有混淆的名称都将不同,并且不会再有 或 堆栈跟踪。有关此 here.
的更多信息
除此之外,Proguard 不会保留有关行号的信息,除非我们按照指示使用 -renamesourcefileattribute
和 -keepattributes
选项。有关此 here.
的更多信息
这些选项会稍微增加您的 apk 大小,但这是完全值得的。这让我省去了很多分析堆栈跟踪的麻烦。
自从我在 Google Play 商店中发布了我的应用程序的新版本后,我在 Android 开发者控制台中收到了崩溃报告。
我在发布新版本后立即上传了 ProGuard mappings.txt
。因此所有日志都未混淆(所有class名称和方法都以明文形式出现)。不过我还是不太确定要不要看。
主要存在三个问题:
- 报告只显示崩溃方法,没有行号。所以我不知道是哪个方法导致了崩溃。
- 一些崩溃报告显示了使用
OR
的不同方法。这是什么意思? - 并非所有报告都经过去混淆处理。有些仍然显示为匿名 class 和方法名称
示例:
// Crash Log with is NOT obfuscated
Caused by: java.lang.NullPointerException:
1: at com.example.MyApp.Path.To.Package.MyClass.myMethod1 (MyClass.java) // <-- No Line Numbers...
or .myMethod2 (MyClass.java) // <-- WHAT does this OR mean???
or .myMethod3 (MyClass.java)
2: at com.example.MyApp.Path.To.Package.MyClass.onCreateView (MyClass.java)
3: at android.support.v4.app.Fragment.performCreateView (Fragment.java)
4: at android.support.v4.app.FragmentManagerImpl.access0 (FragmentManagerImpl.java)
or .access0 (FragmentManagerImpl.java)
or .addFragment (FragmentManagerImpl.java)
or .allocBackStackIndex (FragmentManagerImpl.java)
or .animateRemoveFragment (FragmentManagerImpl.java)
...
5: at android.support.v4.app.FragmentManagerImpl.access0 (FragmentManagerImpl.java)
...
// Other crash seems to show the same problem but is still obfuscated
Caused by: java.lang.NullPointerException:
1: at com.example.MyApp.Path.To.Package.MyClass.a (MyClass.java:89) // <-- Line numbers available here...
2: at com.example.MyApp.Path.To.Package.MyClass.b (MyClass.java:40)
3: at android.support.v4.app.Fragment.performCreateView (Fragment.java)
... // Same call stack as above
问题:
- 为什么有些日志被反混淆,而其他(似乎显示相同的错误)却没有?上传映射文件后创建的两个日志。没有映射文件的旧版本日志显示明确的 "logs are obfuscated" 消息
- 调用堆栈中的
OR
语句是什么意思?这是否意味着这些方法中的每一个都发生了异常(这怎么可能)? - 为什么去混淆后的日志中没有行号?给定的方法很长,没有任何进一步的信息,我不知道到底是什么导致了这个问题。混淆中的行号似乎指向随机行,这些行未以任何方式链接到真实代码。
所以主要问题是:
如何利用日志中的信息查找崩溃的根源?
最好改用 Fabrics。它将给出崩溃报告和行号。
您需要将以下选项添加到 Proguard 配置中:
# This option forces Proguard to use different obfuscated names
# for different members. It avoids the 'or' stack traces.
-useuniqueclassmembernames
# These options produce useful stacktraces preserving line numbers
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
如果没有 -useuniqueclassmembernames
,Proguard 可以为同一 class 中的不同方法分配相同的混淆名称(您可以在 mapping.txt 文件中看到它)。这就是为什么堆栈跟踪知道错误发生在方法 A 或方法 B 中 ,但不知道具体是哪一个。
使用 -useuniqueclassmembernames
选项,所有混淆的名称都将不同,并且不会再有 或 堆栈跟踪。有关此 here.
除此之外,Proguard 不会保留有关行号的信息,除非我们按照指示使用 -renamesourcefileattribute
和 -keepattributes
选项。有关此 here.
这些选项会稍微增加您的 apk 大小,但这是完全值得的。这让我省去了很多分析堆栈跟踪的麻烦。