You need to enable JavaScript to run this app. 升级依赖后出现android.app.ResourcesManager相关ANR死锁问题求助
优惠活动
大模型
产品
解决方案
定价
更多

升级依赖后出现android.app.ResourcesManager相关ANR死锁问题求助

问题背景

近期在Google Play Console中发现应用的ANR量大幅上升,不同触发原因的报告存在一个共同点:主线程和工作线程都被阻塞,且至少有一个线程始终阻塞在访问android.app.ResourcesManager的相关方法上。


示例1

"main" prio=5 tid=1 Blocked

at android.app.ResourcesManager.getAdjustedDisplay (ResourcesManager.java:353)
at android.app.ContextImpl.getDisplayNoVerify (ContextImpl.java:2559)
at android.view.WindowManagerImpl.getDefaultDisplay (WindowManagerImpl.java:164)
at org.n277.lynxlauncher.helper.DeviceUtilities.updateSystemHelper (DeviceUtilities.java:225)
at org.n277.lynxlauncher.views.DragContainerFrameLayout.onApplyWindowInsets (DragContainerFrameLayout.java:231)
at android.view.View.dispatchApplyWindowInsets (View.java:11399)
at android.view.ViewGroup.dispatchApplyWindowInsets (ViewGroup.java:7393)
at android.view.ViewGroup.newDispatchApplyWindowInsets (ViewGroup.java:7418)
at android.view.ViewGroup.dispatchApplyWindowInsets (ViewGroup.java:7400)
at android.view.ViewGroup.newDispatchApplyWindowInsets (ViewGroup.java:7418)
...

"Lynx-Worker" prio=5 tid=17 Blocked

at android.app.ResourcesManager.getOrCreateResources (ResourcesManager.java:865)
at android.app.ResourcesManager.getResources (ResourcesManager.java:982)
at android.app.ActivityThread.getTopLevelResources (ActivityThread.java:2411)
at android.app.ApplicationPackageManager.getResourcesForApplication (ApplicationPackageManager.java:1527)
at android.app.ApplicationPackageManager.getDrawable (ApplicationPackageManager.java:1277)
at android.app.ApplicationPackageManager.loadUnbadgedItemIcon (ApplicationPackageManager.java:2684)
at android.app.ApplicationPackageManager.loadItemIcon (ApplicationPackageManager.java:2655)
at android.content.pm.PackageItemInfo.loadIcon (PackageItemInfo.java:516)
at android.content.pm.ComponentInfo.loadDefaultIcon (ComponentInfo.java:256)
at android.app.ApplicationPackageManager.loadUnbadgedItemIcon (ApplicationPackageManager.java:2687)
at android.app.ApplicationPackageManager.loadItemIcon (ApplicationPackageManager.java:2655)
at android.content.pm.PackageItemInfo.loadIcon (PackageItemInfo.java:516)
at android.content.pm.LauncherActivityInfo.getIcon (LauncherActivityInfo.java:117)
at org.n277.lynxlauncher.visual.c.d.v (SourceFile:1)
at org.n277.lynxlauncher.visual.c.d.u (SourceFile:3)
...

主线程调用windowManager.getDefaultDisplay().getSize()方法获取屏幕尺寸用于测量(适配Android R之前的设备),工作线程则通过LauncherActivityInfo获取应用图标。


示例2

"main" prio=5 tid=1 Blocked

at android.view.WindowManagerImpl.getCurrentBounds (WindowManagerImpl.java:241)
at android.view.WindowManagerImpl.getCurrentWindowMetrics (WindowManagerImpl.java:235)
at org.n277.lynxlauncher.helper.DeviceUtilities.getUsableHeight (DeviceUtilities.java:190)
at org.n277.lynxlauncher.views.FullScreenFrameLayout.onMeasure (FullScreenFrameLayout.java:114)
at android.view.View.measure (View.java:25532)
at android.view.ViewGroup.measureChildWithMargins (ViewGroup.java:6957)
at android.widget.FrameLayout.onMeasure (FrameLayout.java:194)
at android.view.View.measure (View.java:25532)
at android.widget.RelativeLayout.measureChildHorizontal (RelativeLayout.java:735)
...

"Lynx-Worker" prio=5 tid=17 Blocked

at android.app.ResourcesManager.createResources (ResourcesManager.java:846)
at android.app.ResourcesManager.getResources (ResourcesManager.java:947)
at android.app.ActivityThread.getTopLevelResources (ActivityThread.java:2296)
at android.app.ApplicationPackageManager.getResourcesForApplication (ApplicationPackageManager.java:1672)
at android.app.ApplicationPackageManager.getDrawable (ApplicationPackageManager.java:1437)
at android.app.ApplicationPackageManager.loadUnbadgedItemIcon (ApplicationPackageManager.java:2950)
at android.app.ApplicationPackageManager.loadUnbadgedItemIcon (ApplicationPackageManager.java:2953)
at android.app.ApplicationPackageManager.loadItemIcon (ApplicationPackageManager.java:2929)
at android.content.pm.PackageItemInfo.loadIcon (PackageItemInfo.java:271)
at android.content.pm.LauncherActivityInfo.getIcon (LauncherActivityInfo.java:119)
at org.n277.lynxlauncher.visual.c.d.v (SourceFile:1)
at org.n277.lynxlauncher.visual.c.d.u (SourceFile:3)
...

本次主线程调用windowManager.getCurrentWindowMetrics()获取屏幕尺寸用于测量,工作线程依然是通过LauncherActivityInfo获取应用图标。


示例3

和示例2的场景完全一致,只是额外多了一个普通线程也卡在和工作线程完全相同的调用栈上。


已知条件

该问题在上次应用更新前从未出现,未修改过线程相关的逻辑,仅升级了以下几个依赖:

  • buildToolsVersion 从30.0.0升级到30.0.2
  • com.android.billingclient:billing 从3.0.3升级到4.0.0
  • androidx.appcompat:appcompat 从1.2.0升级到1.3.0
  • androidx.recyclerview:recyclerview 从1.1.0升级到1.2.1

目前判断属于多线程访问android.app.ResourcesManager类时产生的死锁问题,怀疑WindowManagerImpl.getCurrentBounds内部也访问了ResourcesManager,只是调用栈没有明确显示。
现在的矛盾点:将应用图标加载逻辑移到主线程会阻塞主线程,LauncherActivityInfo.getIcon方法确实需要访问对应目标应用的资源(而非当前调用方应用的资源),且工作线程还承载了很多其他任务,大量调用的API方法都可能隐式内部访问资源。


解决方案

该问题是AppCompat 1.3.0版本引入的已知缺陷,根源是该版本开始主线程初始化Resources全局配置时会加锁,而子线程访问第三方应用资源时也会请求ResourcesManager的全局锁,两者锁竞争甚至形成死锁最终触发ANR。

可行解决办法按优先级排序:

  1. 降级或升级AppCompat版本
    直接将androidx.appcompat:appcompat回退到1.2.0版本即可消除问题,是成本最低的验证方案。如果需要使用高版本特性,可升级到1.4.0及以上版本,该问题在后续正式版中已修复。
  2. 缓存屏幕参数减少主线程锁请求
    屏幕宽高、可用高度这类参数不会高频变化,可在应用启动主线程空闲阶段一次性计算完成后缓存,后续布局测量逻辑直接读取缓存值,不需要每次都调用getDefaultDisplay或getCurrentWindowMetrics,大幅降低主线程请求ResourcesManager锁的频次。
  3. 第三方资源访问加统一串行锁
    如果暂时不能调整依赖版本,给所有子线程调用LauncherActivityInfo.getIcon这类需要访问外部资源的逻辑加统一的串行锁,确保同一时间只有一个子线程请求ResourcesManager锁,降低和主线程锁竞争的概率。注意不要把主线程逻辑加入该锁范围,避免形成新的死锁。
  4. 预加载应用图标缓存
    应用启动阶段分批预加载常用应用的图标存入内存/磁盘缓存,后续列表渲染时直接读取缓存,减少工作线程运行过程中实时加载图标的频次。

内容的提问来源于stack exchange,提问作者nils277

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 07:45:02