在Android开发过程中,ANR问题可能是非常常见的一个问题,下面我分享一个亲身经历的ANR问题以及解决方法。
由于权限的原因,一般使用:
adb pull /data/anr/anr_2022-08-04-19-43-53-830 ./
会提示:
adb: error: failed to copy '/data/anr/anr_2022-08-04-19-43-53-830' to './/anr_2022-08-04-19-43-53-830': remote open failed: Permission denied
如果倒不出来,可以采用
adb bugreport
执行这个命令之后会在/home/ms(这里是我的路径)生成一个zip文件: bugreport-crosshatch-SPB5.210812.002-2022-08-04-19-52-30.zip
将这个zip解压开得到:
在/FS/data/anr 下面就是产生anr的日志文件
打开最新的一个anr日志文件,内容很多,可以通过搜索 main来快速定位到日志:
"main" prio=5 tid=1 Native
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x71bb1108 self=0x7aaf011010
| sysTid=11840 nice=-10 cgrp=default sched=0/0 handle=0x7be4f0a4f8
| state=R schedstat=( 34563882813 172228872 5118 ) utm=3400 stm=55 core=6 HZ=100
| stack=0x7fc17f0000-0x7fc17f2000 stackSize=8188KB
| held mutexes=
native: #00 pc 00000000005f29dc /data/app/~~HpEMONV-UKwHtGltDb4G-w==/com.meishe.ms240sdkdemo-9NftEp5LVuvFBG2ZxJvKVQ==/lib/arm64/libNvStreamingSdkCore.so (???)
at com.meicam.sdk.NvsTimeline.nativeApplyThemeTemplate(Native method)
at com.meicam.sdk.NvsTimeline.applyThemeTemplate(NvsTimeline.java:1466)
at com.czc.cutsame.CutSameEditorActivity.createTimeline(CutSameEditorActivity.java:250)
at com.czc.cutsame.CutSameEditorActivity.initData(CutSameEditorActivity.java:118)
at com.meishe.base.model.BaseActivity.onCreate(BaseActivity.java:48)
at com.czc.cutsame.CutSameEditorActivity.onCreate(CutSameEditorActivity.java:95)
at android.app.Activity.performCreate(Activity.java:8051)
at android.app.Activity.performCreate(Activity.java:8031)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1329)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3612)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3796)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2214)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7842)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
1: pid: 8625 对的上
2: cmd line: 包名对得上 check完毕
3: 查看UI线程,搜索main
native: #00 pc 00000000005f29dc /data/app/~~HpEMONV-UKwHtGltDb4G-w==/com.meishe.ms240sdkdemo-9NftEp5LVuvFBG2ZxJvKVQ==/lib/arm64/libNvStreamingSdkCore.so (???)
通过上面这个可以看出这个是一个native层的问题,给出出问题的so库的符号地址:00000000005f29dc
2.通过aarch64-linux-android-addr2line 命令解析符号地址:00000000005f29dc
aarch64-linux-android-addr2line 这个命令存在 /home/ms/tools/android-ndk-r21e/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin(笔者是这个路径)
可以将这个路径配置到环境变量,方便直接使用
解析错误符号地址的命令:aarch64-linux-android-addr2line -C -f -e <对应带符号表的so库> <8位内存地址>
./aarch64-linux-android-addr2line -C -f -e '/home/ms/ftp-download/sdk/3.5.1/NvStreamingSdk_Android_3.5.1.8_20220804_102011_ARScene_MS_Symbol/NvStreamingSdk_Android_3.5.1.8_20220804_102011_Symbol/android_arm64/libNvStreamingSdkCoreSymbol.so' 0005f29dc
注意这里的so库是对应的带符号的so库才可以
解析的结果是:
错误符号解析的结果:能定位到问题是由于CNvProjTimeline::ResetThemeTemplate() 这个方法导致的。
这个ANR问题就定位到原因了。
3.小技巧总结
Cmd line:后边跟的是包名,包名能对上就能定位成功了
----- pid 11840 at 2022-08-04 19:43:53.853466911+0800 -----
...
...
Total number of allocations 768630 //进程创建到现在一共创建了多少对象
Total bytes allocated 67MB // 进程创建到现在一共申请了多少内存
Total bytes freed 55MB // 进程创建到现在一共释放了多少内存
Free memory 20MB // 空闲内存(可用内存)
Free memory until GC 20MB // GC前的空闲内存
Free memory until OOME 243MB // OOM之前的可用内存,当这个值很小的时候,已经处于内存紧张状态,应用可能占用了过多的内存
Total memory 32MB // 当前总内存(已用+可用)
Max memory 256MB // 进程最多能申请的内存
从日志里边能看到有三个线程,一个是 Signal Catcher
线程,一个是 main
线程,一个是 Jit thread pool worker thread 0
,他们的线程状态分别是 Runnable
、 blocked
和 native
状态。
线程的状态:
native 状态不在类别之内,这个表示正在执行JNI函数,也是runnable状态。
堆栈信息是我们分析ANR的第一个重要的信息,一般来说:
另外,在 anr 日志中,还有一些常见参数,他们的含义如下: