Android 13后台频繁触发java.util.ConcurrentModificationException问题咨询
Android 13下PropertyInvalidatedCache触发ConcurrentModificationException的解决方案
问题概述
仅在Android 13系统中,后台会高频率抛出java.util.ConcurrentModificationException,触发点为系统执行onTrimMemory操作、遍历PropertyInvalidatedCache中的Activity缓存时。异常栈如下:
Exception java.util.ConcurrentModificationException: at java.util.WeakHashMap$HashIterator.nextEntry (WeakHashMap.java:807) at java.util.WeakHashMap$KeyIterator.next (WeakHashMap.java:840) at java.util.AbstractCollection.toArray (AbstractCollection.java:144) at java.util.ArrayList.<init> (ArrayList.java:191) at android.app.PropertyInvalidatedCache.getActiveCaches (PropertyInvalidatedCache.java:1413) at android.app.PropertyInvalidatedCache.onTrimMemory (PropertyInvalidatedCache.java:1615) at android.app.ActivityThread.handleTrimMemory (ActivityThread.java:6361) at android.app.ActivityThread.-$$Nest$mhandleTrimMemory at android.app.ActivityThread$ApplicationThread.lambda$scheduleTrimMemory$0 (ActivityThread.java:1746) at android.app.ActivityThread$ApplicationThread$$ExternalSyntheticLambda2.accept at com.android.internal.util.function.pooled.PooledLambdaImpl.doInvoke (PooledLambdaImpl.java:281) at com.android.internal.util.function.pooled.PooledLambdaImpl.invoke (PooledLambdaImpl.java:204) at com.android.internal.util.function.pooled.OmniFunction.run (OmniFunction.java:97) at android.os.Handler.handleCallback (Handler.java:942) at android.os.Handler.dispatchMessage (Handler.java:99) at android.os.Looper.loopOnce (Looper.java:201) at android.os.Looper.loop (Looper.java:288) at android.app.ActivityThread.main (ActivityThread.java:7884) at java.lang.reflect.Method.invoke at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:936)
异常原因
从栈信息可以看出,PropertyInvalidatedCache.getActiveCaches()会将内部WeakHashMap的键集合转为ArrayList,这个过程依赖迭代器遍历。但WeakHashMap本身不是线程安全的,当系统在onTrimMemory触发遍历的同时,若有其他操作(比如Activity的创建/销毁)修改了这个缓存Map,就会触发迭代器的fail-fast机制,直接抛出异常。这是Android 13系统层面的并发处理漏洞。
可行解决方案
1. 规避触发场景
- 减少后台trim阶段的Activity缓存变更:避免在APP进入后台、系统可能触发
onTrimMemory的时机,执行启动/销毁Activity、修改Window属性等操作。 - 主动清理Activity缓存:使用
Activity.finishAndRemoveTask()替代普通的finish(),彻底移除Activity的系统缓存,降低缓存Map的修改频率。 - 优化Activity栈管理:避免频繁创建临时Activity,减少系统缓存的压力。
2. 反射加锁修复(谨慎使用)
通过反射获取系统缓存的WeakHashMap实例,在所有可能修改缓存的操作前后添加同步锁,避免遍历和修改同时发生:
import android.app.PropertyInvalidatedCache; import java.lang.reflect.Field; import java.util.WeakHashMap; import java.util.concurrent.locks.ReentrantLock; public class CacheSyncUtil { private static final ReentrantLock CACHE_LOCK = new ReentrantLock(); private static WeakHashMap activityCache; static { // 仅在Android 13环境下初始化 if (android.os.Build.VERSION.SDK_INT == android.os.Build.VERSION_CODES.TIRAMISU) { try { Field cacheField = PropertyInvalidatedCache.class.getDeclaredField("sActivityCache"); cacheField.setAccessible(true); activityCache = (WeakHashMap) cacheField.get(null); } catch (Exception e) { e.printStackTrace(); } } } public static void executeWithCacheLock(Runnable action) { if (activityCache == null) { action.run(); return; } CACHE_LOCK.lock(); try { action.run(); } finally { CACHE_LOCK.unlock(); } } }
使用示例:
// 启动Activity时加锁 CacheSyncUtil.executeWithCacheLock(() -> { startActivity(new Intent(this, TargetActivity.class)); }); // 销毁Activity时加锁 CacheSyncUtil.executeWithCacheLock(() -> { finish(); });
注意:反射操作可能受厂商定制系统限制,需做好异常捕获,仅在Android 13环境下启用。
3. 等待系统修复
这是Android 13的系统bug,后续Android版本(如14及以上)已修复此问题,可引导用户升级系统或等待厂商推送补丁。
内容的提问来源于stack exchange,提问作者谢鹦鹉
相关产品推荐
相关产品推荐

