会造成 ANR 的场景:
ANR 问题分析步骤
1. 确认友商
如果是三方应用的 anr 问题且必现问题或高概率发生,先确认 pixel 原生机是否可以同样复现,以及友商手机可否复现,分为 4 种情况。如果判断为三方应用的问题,可转三方质量商务处理并适当贴一些原因分析。
1.1 三方应用情况分类
我司
原生 Pixel
友商
决策
有
解决
有
有
三方解决 + 评审是否做适配
有
有
评审是否解决(少见)
有
有
有
三方解决 + 评审是否做适配
2. 确认问题发生时间点找到 log 对应位置分析
打开 ems_logs/zipLog ,找到问题发生对应时间的那份 ANR 解压打开进行 log 分析如
APP_ANR@22439_ com.gotokeep.keep _2023-05-05- 19-17-16.808 .txt
或 FATAL_2023-05-05-19-17-16 / anr_2023-01-24-15-47-00-907 文件
或 23-05-06--10-39-05_recording / mobile / main.log(logcat/main.log) 中查询 “ ActivityManager: ANR in”
或 23-05-06--10-39-05_recording / mobile / event.log(logcat/event.log) 中查询 “ am_anr”
2.1 log 特殊分析情况
(案例)
如以下微信语音通话同时播放音乐,反复开关扬声器,会导致系统崩溃的问题
Plain Text ----- pid 32167 at 2023-01-24 15:47:00.983416988+0800 ----- Cmd line: com.android.systemui ...... "main" prio=5 tid=1 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72b41528 self=0xb4000079cb2bf380 | sysTid=32167 nice=0 cgrp=foreground sched=0/0 handle=0x7b958c64f8 | state=S schedstat=( 8059148030 8008439373 22623 ) utm=609 stm=196 core=6 HZ=100 | stack=0x7ff826a000-0x7ff826c000 stackSize=8188KB | held mutexes= native: #00 pc 00000000000a5b8c /apex/com.android.runtime/lib64/bionic/libc.so (__ioctl+12) (BuildId: 2938f6235116cbc48464ee0f7622625e) native: #01 pc 000000000005c9e0 /apex/com.android.runtime/lib64/bionic/libc.so (ioctl+160) (BuildId: 2938f6235116cbc48464ee0f7622625e) native: #02 pc 000000000005c2a0 /system/lib64/ libbinder .so (android::IPCThreadState::talkWithDriver(bool)+284) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #03 pc 000000000005d4fc /system/lib64/ libbinder .so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+76) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #04 pc 000000000005d238 /system/lib64/ libbinder .so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+224) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #05 pc 0000000000054a44 /system/lib64/ libbinder .so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+192) (BuildId: b5f24c77eb4cb8038980e4e1f81dcfc0) native: #06 pc 0000000000176b98 /system/lib64/libandroid_runtime.so (android_os_BinderProxy_transact(_JNIEnv*, _jobject*, int, _jobject*, _jobject*, int)+212) (BuildId: 958e4dab31a35b8c82656bf5f30a2d95) at android.os.BinderProxy.transactNative(Native method) at android.os.BinderProxy.transact(BinderProxy.java:584) at android.media.IAudioService $Stub$Proxy.getStreamVolume(IAudioService.java:3909) at android.media.AudioManager.getStreamVolume (AudioManager.java:1231) at com.flyme.systemui.volume.QSVolumeControllerImpl.getStreamVolume( QSVolumeControllerImpl.kt:265) at com.flyme.systemui.volume.QSVolumeControllerImpl.access$getStreamVolume(QSVolumeControllerImpl.kt:43) at com.flyme.systemui.volume.QSVolumeControllerImpl$mCommunicationDeviceChangedListener$2$1.onCommunicationDeviceChanged(QSVolumeControllerImpl.kt:93) ......
结论:
可见是 com.flyme.systemui.volume.QSVolumeControllerImpl.getStreamVolume 跨进程调用到 AudioService 的 getStreamVolume 里面卡住了,那问题就是 systemui 主线程频繁调用 getStreamVolume 导致 或 AudioService 的 getStreamVolume 本身有问题导致。显然前者非原生,发生问题的概率更大。后续解决方案没有修改业务逻辑,但在 systemui 调用 getStreamVolume 获取音量之间添加了一个 cache.java ,里面存放一些情况下不变的值用于直接获取而不是频繁从 AudioService 获取来解决问题。
当然应用也可以尝试把此访问业务放到子线程里做事,只不过这里涉及到主线程 UI 的实时更新不方便。
(如果认为证据少,也可以通过 找 binder 对端 的方法说明资源正在被谁占用导致 systemui 卡住,不过比较繁琐)就用本例来找以下 binder 对端。
2.1.1 binder 找对端
(在 anrlog 中搜索 Blocked 也可以发现是具体卡在了哪里如下)
Plain Text "main" prio=5 tid=1 Blocked | group="main " sCount=1 ucsCount=0 flags=1 obj=0x72b41528 self=0xb4000079cb2bf380 | sysTid= 2719 nice=-2 cgrp=foreground sched=0/0 handle=0x7b958c64f8 | state=S schedstat=( 51445309149 81742345474 421858 ) utm=3031 stm=2113 core=2 HZ=100 | stack=0x7ff826a000-0x7ff826c000 stackSize=8188KB | held mutexes= at com.android.server.audio.AudioService.getDeviceSetForStream(AudioService.java:7041) - waiting to lock < 0x01384d82 > (a java.lang.Class<com.android.server.audio.AudioService$VolumeStreamState>) held by thread 110 at com.android.server.audio.AudioService. getDeviceForStream (AudioService.java:6948) at com.android.server.audio.AudioService. getStreamVolume (AudioService.java:4760) at android.media.AudioManager. getStreamVolume (AudioManager.java:1231) ......
搜索 2719 可知是卡在了 system_server
Plain Text ----- pid 2719 at 2023-01-24 15:47:01.675316363+0800 ----- Cmd line: system_server ......
在同文件夹下的 binderinfo 文件中搜索 systemui 的 pid 32167
SQL outgoing transaction 8372988: 0000000000000000 from 32167 : 32167 to 2719 : 5009 code 12 flags 10 pri 0:120 r1 incoming transaction 8372988: 0000000000000000 from 32167 : 32167 to 2719 : 5009 code 12 flags 10 pri 0:120 r1 node 11752 size 76:0 data 0000000000000000
可知此时 systemui 正在和 system_server 通信
在 anrlog 中 5009 线程可知:
SQL "binder: 2719_E " prio=5 tid=180 Blocked | group=" main " sCount=1 ucsCount=0 flags=1 obj=0x1388d458 self=0xb4000079cb46c930 | sysTid= 5009 nice=0 cgrp=foreground sched=0/0 handle=0x775456acb0 | state=S schedstat=( 13630495183 12263926909 72029 ) utm=861 stm=501 core=0 HZ=100 | stack=0x7754473000-0x7754475000 stackSize=991KB | held mutexes= at com.android.server.audio.AudioDeviceBroker.isDeviceOnForCommunication(AudioDeviceBroker.java:513) - waiting to lock < 0x07d20c85 > (a java.lang.Object) held by thread 111 at com.android.server.audio.AudioDeviceBroker. isBluetoothScoOn (AudioDeviceBroker.java:568) at com.android.server.audio.AudioService.isBluetoothScoOn(AudioService.java:6143) at android.media.IAudioService$Stub.onTransact(IAudioService.java:2164) at android.os.Binder.execTransactInternal(Binder.java:1285) at android.os.Binder.execTransact(Binder.java:1244) system_server 的 binder 对端 2719_E 线程中 isBluetoothScoOn 正在被调用,但其锁 0x07d20c85 被线程 111 占用了, "AudioDeviceBroker" prio=5 tid=111 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x13889128 self=0xb4000079cb3c3f60 | sysTid= 3454 nice=0 cgrp=foreground sched=0/0 handle=0x773a719cb0 ...... at com.android.server.audio.AudioDeviceBroker$BrokerHandler.handleMessage(AudioDeviceBroker.java:1477) - locked <0x05f1adfc> (a java.lang.Object) - locked < 0x07d20c85 > (a java.lang.Object) 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 com.android.server.audio.AudioDeviceBroker$BrokerThread.run(AudioDeviceBroker.java:1331)
在同文件夹下的 binderinfo 文件中搜索 3534
SQL outgoing transaction 8379166: 0000000000000000 from 2719 : 3454 to 1643 : 26372 code 51 flags 10 pri 0:120 r1 incoming transaction 8379166: 0000000000000000 from 2719 : 3454 to 1643 : 26372 code 51 flags 10 pri 0:120 r1 node 10250 size 140:0 data 0000000000000000
可知此时 system_server 的这个 binder 线程正在和 1643 进程的 26372 线程通信,在 anrlog 中搜索 1643
SQL ----- pid 1643 at 2023-01-24 15:47:04.702978758+0800 ----- Cmd line: /system/bin/ audioserver
此时 system_server 的这个 binder 线程正在和通信, system_server 不选择使用其他 binder 线程的原因估计是其进程的 binder 线程数量耗尽了。
继续搜索 26372 线程
SQL "binder: 1643_B " sysTid= 26372 #00 pc 000000000004ea70 /apex/com.android.runtime/lib64/bionic/libc.so (syscall+32) (BuildId: 2938f6235116cbc48464ee0f7622625e) #01 pc 0000000000053458 /apex/com.android.runtime/lib64/bionic/libc.so (__futex_wait_ex(void volatile*, bool, int, bool, timespec const*)+148) (BuildId: 2938f6235116cbc48464ee0f7622625e) #02 pc 00000000000b9934 /apex/com.android.runtime/lib64/bionic/libc.so (pthread_cond_timedwait+140) (BuildId: 2938f6235116cbc48464ee0f7622625e) #03 pc 000000000004ecb0 /system/lib64/lib audiopolicyservice .so (android:: AudioPolicyService::AudioCommandThread::sendCommand (android::sp<android::AudioPolicyService::AudioCommandThread::AudioCommand>&, int)+320) (BuildId: 67a27d80d1c32888be575cc15b943518)
可知锁被占用在 audiopolicyservice 内调用 AudioPolicyService::AudioCommandThread::sendCommand 处,此处是原生代码,属于正常耗时流程。 所以还是需要 systemui 在调用处做优化。
(案例)
Keep app 点击运动开始后息屏静置,再点击停止发生不成功的 activity 跳转( OutdoorTrainingV2Activity 跳转到 Maictivity ), Keep 应用的 OutdoorWorkoutBackgroundService 调用 onDestroy ,走到了 /system/bin/mediaserver 的 MediaPlayer.java ——> tryToDisableNativeRoutingCallback ——> testDisableNativeRoutingCallbacksLocked ——> native_enableDeviceCallback
——> 到 JNI 底层长时间未完成跳出,耗时超过 5 秒触发 anr
2.1.2 trace 文件分析
也可以通过把 log 里的 trace 文件上传到谷歌的 perfettoUI 网址 https://www.ui.perfetto.dev/#!/record/instructions 中分析。如上面的案例:
后续发现是 mediaservice 里我们写了一段“同步”代码导致,取消同步不阻塞调用 audio write ,问题即可解决。
2.1.3 Anr 日志文件无效
PHP "main" prio=5 tid=1 Native | group="main" sCount=1 dsCount=0 obj=0x7685ba50 self=0x7fb0840a00| sysTid=1460 nice=-10 cgrp=default sched=0/0 handle=0x7fb4824aa0| state=S schedstat=( 213445473008 99617457476 724519 ) utm=14518 stm=6826 core=0 HZ=100| stack=0x7fe82c6000-0x7fe82c8000 stackSize=8MB| held mutexes= kernel: __switch_to+0x70/0x7c kernel: SyS_epoll_wait+0x2d4/0x394 kernel: SyS_epoll_pwait+0xc4/0x150 kernel: el0_svc_naked+0x24/0x28 native: #00 pc 000000000001bf2c /system/lib64/libc.so (syscall+28) native: #01 pc 00000000000e813c /system/lib64/libart.so (_ZN3art17ConditionVariable16WaitHoldingLocksEPNS_6ThreadE+160) native: #02 pc 000000000054b6f8 /system/lib64/libart.so (_ZN3artL12GoToRunnableEPNS_6ThreadE+328) native: #03 pc 000000000054b56c /system/lib64/libart.so (_ZN3art12JniMethodEndEjPNS_6ThreadE+28) native: #04 pc 00000000008ccc50 /system/framework/arm64/boot-framework.oat (Java_android_os_MessageQueue_nativePollOnce__JI+156) at android.os.MessageQueue.nativePollOnce(Native method) at android.os.MessageQueue.next(MessageQueue.java:323)
3. 尝试复现问题(测试提供的 log 不足)
3.1 整机状态良好的情况下复现了问题
APP_ANR 文件中搜索“ main” ,查看发生 anr 时此刻主线程堆栈,通常来说,如果打印的堆栈是该进程内部的堆栈,并且经过业务证实这段代码确实可能存在耗时,那么可以给三方商务根据 callstack 位置找到代码修改即可,如果友商适配了此问题也可以考虑看我司能否适配。(这种问题一般属于严重三方问题)
(案例)
下图为美团滑动 anr 问题
SQL Process: com.sankuai.meituan PID: 32180 UID: 10214 Frozen: false Flags: 0x38b83e44 Package: com.sankuai.meituan v1200090209 (12.9.209) Foreground: Yes Process-Runtime: 91290258 Activity: com.sankuai.meituan/com.dianping.live.live.mrn.MLiveMRNActivity ErrorId: 8dd92ab2-c430-44a2-a68b-7a34b77d7cdd Build: meizu/meizu_20Pro_CN/meizu20Pro:13/TKQ1.221114.001/1673297425:user/release-keys Loading-Progress: 1.0 Dropped-Count: 0 ShouldUpload: true ZipLogFile: /data/misc/ems_logs/zipLog/APP_ANR@32180_com.sankuai.meituan_2023-04-25-20-32-03.319.zip Input dispatching timed out (492e397 com.sankuai.meituan/com.dianping.live.live.mrn.MLiveMRNActivity (server) is not responding. Waited 5001ms for FocusEvent(hasFocus=true)) ==================================================================================================== ----- Output from /proc/pressure/memory ----- some avg10=0.00 avg60=0.03 avg300=0.12 total=140081266( 占 140M 并不高 full avg10=0.00 avg60=0.00 avg300=0.00 total=110897319 ----- End output from /proc/pressure/memory ----- ----- Output from /proc/pressure/cpu ----- CPU usage from 0ms to 5808ms later (2023-04-25 20:31:57.475 to 2023-04-25 20:32:03.283): 155% 32180/com.sankuai.meituan : 133% user + 21% kernel / faults: 19145 minor 944 major 67% 2867/system_server: 30% user + 36% kernel / faults: 70692 minor 181 major 51% 1649/vendor.qti.hardware.display.composer-service: 11% user + 40% kernel / faults: 1288420 minor 33% 3926/com.android.systemui: 20% user + 13% kernel / faults: 2978 minor 42 major 30% 1773/surfaceflinger: 18% user + 12% kernel / faults: 3675 minor 1 major ...... 0.1% 31679/system-log: 0% user + 0.1% kernel 0.1% 32211/com.flyme.systemuiex: 0% user + 0.1% kernel / faults: 1 minor +0% 7191/kworker/6:0: 0% user + 0% kernel 67% TOTAL (负载不算太高 : 36% user + 28% kernel + 0.2% iowait + 2.1% irq + 0.3% softirq ...... "main" prio=5 tid=1 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x72f7f548 self=0xb400007bb6042c00 | sysTid=32180 nice=0 cgrp=background sched=0/0 handle=0x7c5b0a14f8 | state=S schedstat=( 7273443913 816442287 15156 ) utm=578 stm=149 core=0 HZ=100 | stack=0x7fcb618000-0x7fcb61a000 stackSize=8188KB | held mutexes= native: #00 pc 0000000000089630 /apex/com.android.runtime/lib64/bionic/libc.so (syscall+32) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #01 pc 000000000008e018 /apex/com.android.runtime/lib64/bionic/libc.so ( __futex_wait_ex (void volatile*, bool, int, bool, timespec const*)+148) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #02 pc 00000000000f43dc /apex/com.android.runtime/lib64/bionic/libc.so (pthread_cond_wait+80) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #03 pc 000000000028a06c /system/lib64/libhwui.so (android::uirenderer::renderthread::DrawFrameTask::drawFrame()+360) (BuildId: 46f2295089591c6e67e210338c5b1e07) at android. graphics .HardwareRenderer.nSyncAndDrawFrame(Native method) at android. graphics .HardwareRenderer.syncAndDrawFrame(HardwareRenderer.java:466) at android.view. ThreadedRenderer.draw (ThreadedRenderer.java:810) at android.view.ViewRootImpl.draw(ViewRootImpl.java:4647) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4358) ......
(看堆栈在 graphics 表明可能是其反复调用绘制导致),后续美团更新解决了。
(案例)
案发时间点附近,发现大量的 GC 片段且很多 GC 耗时都较长, Clamp target GC heap from 说明当前应用堆使用已超出上限 512M ,为了满足新分配的对象内存需求,调整目标堆上限值,且系统一直持续不断的对该应用进行阻塞 GC(GC 分为不同力度,阻塞 GC 说明应用此时内存情况比较糟糕 ) ,尽管应用持续不断的阻塞 GC ,应用内存依旧没有降下来。这种情况下很可能是出现了应用内存泄漏的情况。
3.1.1 发生 anr 的进程占比很高
那要让此应用看下原因,如此处的 155% 32180/com.sankuai.meituan 。很可能是应用在做耗时操作,频繁绘制、网络访问、读取文件等。有时候可能会打印 _futex_wait_ex 如
SQL "main" prio=5 tid=1 Native | group="main" sCount=1 ucsCount=0 flags=1 obj=0x7169d2a8 self=0xb40000767d242c00 | sysTid=29357 nice=-20 cgrp=top-app sched=1073741825/1 handle=0x772cdd84f8 | state=S schedstat=( 3300558764759 160006040018 5764104 ) utm=239875 stm=90180 core=3 HZ=100 | stack=0x7fdeca9000-0x7fdecab000 stackSize=8188KB | held mutexes= native: #00 pc .../apex/com.android.runtime/lib64/bionic/libc.so (syscall+32) (BuildId: c7a69636ad70437896f8f6cfecde9001) native: #01 pc .../apex/com.android.runtime/lib64/bionic/libc.so (_ _futex_wait_ex (void volatile*, bool, int, bool, timespec const*)+148) (BuildId: c7a69636ad70437896f8f6cfecde9001)
3.1.2 通过同时其他进程的负载状况推测出应用的什么逻辑卡住了
如另外当出现大量的 IO 操作的时候,应用主线程的 Uninterruptible Sleep 也会变多,此时涉及到 io 操作(比如 view ,读文件,读配置文件、读 odex 文件),都会触发 Uninterruptible Sleep , 导致整个操作的时间变长。
缺页次数 fault,major 表示内存的缺页次数,可以理解为进程在做 IO 操作 ;minor 表示高速缓存中的缺页次数,可以理解为进程在做内存访问 。
3.1.3 直接看下系统日志,可能是应用的内存使用导致的问题
关于应用内存使用不当,通常有如下几种情况,这些情况虽不一定会导致 ANR ,但是应用操作上的卡顿可能在所难免, log 关键词 GC Alloc 。
频繁的生成临时对象导致堆内存增长迅速
达到下次堆 GC 触发阈值后便会触发 Bg GC ,进而导致回收线程跑大核和前台应用争抢 CPU 。
另外 GC 回收阶段会存在一次锁堆
此时应用的主线程会被 pause ,这种情况下势必会造成应用使用卡顿甚至 ANR 。
应用发生了较为严重的内存泄漏
此种情况比较常见,会导致 GC 一直无法回收足够的内存,可以 log 搜索关键词证明,也可以通过 Android Studio 的 Profiler 工具直接进行观测到应用占用内存不断增长。
应用申请大内存触发阻塞 GC
以便应用能够申请到足够的内存,但这种情况通常会引起应用界面的黑屏或者明显的卡顿。
应用调用显式 GC 接口即 System.gc()
我们知道系统低内存时会触发 OnTrimMemory 回调,如果应用在 OnTrimMemory 中并且是在主线程中直接调用显式 GC 接口即 System.gc() ,也容易引起应用卡顿,对于这个接口的使用需要谨慎。
还可以看 am_pss 打印的进程资源状态如
I am_pss : [29357,10304,com.tencent.mm, 1445406720 ,980193280,411634688,1198116864,1,10,87] 说明当时微信的内存占比比较高( 1.445G ),系统很可能处于低内存状态。
3.1.4 通过 perfettoUI 分析
此时最需要跑的当前进程是否是跑到了非超大核上( cpu7 一般是超大核,另外好的芯片还会有两个大核、中核,序号依次变小);以及现在手机 cpu 正在做什么耗时的操作如绘制类图样和渲染器( graphics 、 renderer );或者可能是因为应用导致了系统需要频繁的 GC ,导致 GC 的程序跑到了大核上等。
3.1.5 binder 阻塞的情况往往是 binder 耗尽
应用最多支持 16 个 binder 线程, SystemServer 支持最多 32 个 binder 线程。
举个例子,进程 A 短时间内发送很多 Binder 请求给进程 B ,这种情况下就有可能会导致在短时间内,接收端进程 B 的 Binder 线程池中的 16 个 Binder 线程,都用来响应进程 A 的 Binder 请求,也就是我们常说的 Binder 线程池耗尽的情况,此时进程 B 无法处理进程 A 发过来的新的 Binder 请求。如:
SQL 行 19: ----- pid 32167 at 2023-01-24 15:47:00.983416988+0800 ----- 行 250: | sysTid=32167 nice=0 cgrp=foreground sched=0/0 handle=0x7b958c64f8 行 370: "binder:32167_1" prio=5 tid=13 Native 行 388: "binder:32167_2" prio=5 tid=14 Native 行 406: "binder:32167_3" prio=5 tid=15 Native 行 424: "binder:32167_4" prio=5 tid=16 Native 行 632: "HwBinder:32167_1" prio=5 tid=31 Native 行 698: "binder:32167_5" prio=5 tid=18 Native 行 716: "binder:32167_6" prio=5 tid=35 Native 行 734: "binder:32167_7" prio=5 tid=36 Native 行 752: "binder:32167_8" prio=5 tid=37 Native 行 786: "binder:32167_9" prio=5 tid=39 Native 行 804: "binder:32167_A" prio=5 tid=40 Native 行 892: "binder:32167_B" prio=5 tid=45 Native 行 910: "binder:32167_C" prio=5 tid=46 Native 行 1143: "binder:32167_D" prio=5 tid=3 Native 行 1177: "binder:32167_E" prio=5 tid=60 Native 行 1195: "binder:32167_ F " prio=5 tid=63 Native 行 1566: "binder:32167_2" prio=5 (not attached) 行 1762: ----- end 32167 -----
关于 Binder 耗尽的情况,通常是由于代码设计上的缺陷,导致短时间内高频发起 Binder ;也有可能是好几个应用同时在对同一个进程如 systemserver 发起 binder 调用;还有一种情况也可能会出现,那就是在 Monkey 测试环境下。
3.2 只能在高负载情况下才能复现问题
(案例)
如下为 systemui 问题,高负载场景(用户反馈的 log
SQL Process: com.android.systemui PID: 7688 UID: 10090 Frozen: false Flags: 0x38c8be0d Package: com.android.systemui v10001000 (10.1.0) Foreground: No Process-Runtime: 135945 ErrorId: d548b2d2-c720-4d86-bbc5-003dda4158b8 Build: meizu/meizu_18Pro_CN/meizu18Pro:13/TKQ1.221114.001/1681589413:user/release-keys Loading-Progress: 1.0 Dropped-Count: 0 ShouldUpload: true ZipLogFile: /data/misc/ems_logs/zipLog/APP_ANR@7688_com.android.systemui_2023-04-20-19-30-55.031.zip Input dispatching timed out (3c2477c NotificationShade (server) is not responding. Waited 5000ms for MotionEvent) ...... CPU usage from 34ms to -9667ms ago (2023-04-20 19:30:45.266 to 2023-04-20 19:30:54.967): 103% 1518/system_server: 45% user + 58% kernel / faults: 72387 minor 47 major 38% 1055/surfaceflinger: 23% user + 14% kernel / faults: 2773 minor 15% 13091/com.sup.android.superb: 11% user + 4.4% kernel / faults: 32108 minor 98 major ...... +0% 16709/logcat: 0% user + 0% kernel 92% TOTAL: 52% user + 36% kernel + 0.3% iowait + 2.5% irq + 0.7% softirq
比如此处 92% TOTAL 表明高负载,分析 top 前 5 看下谁占用系统资源比较多,看属于是正常占用还是异常 . 高负载下一般要分情况:
3.2.1 低内存时系统往往会竭尽可能的回收内存
可能触发的 fast path 回收 \ kswapd 回收 \ direct reclaim 回收 \ LMK 杀进程回收等行为,都会造成 do_page_fault 高频发生, log 中也会有大量 lowmemorykiller 打印。所以,分析 ANR 问题时如果遇到 kswapd 占据很高 (top3) ,则认为该问题受系统低内存影响很大。
3.2.2 看是否和系统的优化冻结有关
在 anr 文件中看 “ Frozen: false” 处是否为 true ,移交冻结伙伴看是否是不合理的冻结或未解冻导致。
3.2.3 受环境温度或负载影响
手机温度较高,也会触发温控,但一般是结果而不是造成 anr 的原因。(在提供的日志文件中 找到 kernel 搜索 THERMGRP 关键字,默认这个是 20s 查询一次 如果需要排查的更精细, echo 5 > /sys/class/meizu/mz_timestamp/timestamp_intv 这个命令可以修改为 5s 一次。
[cpu 温度 PCB 温度 GPU 温度 小核当前频率 大核当前频率 超大频率 GPU 当前频率 电流 ]
对比机器的配置文件或直接输入 adb shell thermal-engine-v2 -o 可以看到一份配置信息
且在 /vendor/etc/ 下的 thermal.xxx.conf 文件 有更多的关于 cpu 频率的配置信息(其中 mid- 普通, game- 游戏, super- 高帧率游戏)如:
3.2.4 有其他应用或进程占据较高的负载
可能是由于其导致的 io 、 media 、震动等资源的占用,发生 anr 的应用只不过是替罪羊。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)