React Native调用自定义Native模块触发ANR问题排查求助
核心问题定位
从ANR日志的main线程栈可明确:
ANR发生在应用启动阶段的MainApplication.onCreate流程中,调用链为:MainApplication.onCreate → MyCustomSDK.initialise → ApiCalls.allAPIsCall → VolleySingleton.addToRequestQueue → VolleySingleton.getRequestQueue → Volley.newRequestQueue → RequestQueue.start → Thread.start → Thread.nativeCreate
主线程卡在ConditionVariable::WaitHoldingLocks,说明主线程在创建Volley线程池时被阻塞,无法及时处理系统消息,最终触发ANR。
可能原因及对应修复
1. 主线程执行Volley初始化与网络请求
Volley的newRequestQueue虽会在后台创建线程,但如果allAPIsCall直接在主线程发起请求或包含同步阻塞逻辑,会占用主线程导致ANR。
修复方案:
将SDK初始化和Volley请求移至后台线程执行:
// 修改MyCustomSDK的initialise方法 companion object { fun initialise(context: Context) { Thread { ApiCalls.allAPIsCall(context) }.start() // 也可使用Coroutine、HandlerThread等Android原生异步方案 } }
2. Volley单例初始化的线程安全竞争
你的VolleySingleton使用了Kotlin的synchronized lazy实现单例,虽线程安全,但如果主线程与其他线程同时触发初始化,可能引发锁竞争阻塞主线程。
修复方案:
提前在后台线程完成Volley单例初始化,避免主线程触发:
class VolleySingleton private constructor(context: Context) { val requestQueue: RequestQueue by lazy { Volley.newRequestQueue(context.applicationContext) } companion object { @Volatile private var INSTANCE: VolleySingleton? = null fun getInstance(context: Context): VolleySingleton { return INSTANCE ?: synchronized(this) { INSTANCE ?: VolleySingleton(context).also { INSTANCE = it } } } // 后台提前初始化方法 fun preInit(context: Context) { Thread { getInstance(context).requestQueue }.start() } } } // 在MainApplication.onCreate中先执行后台初始化 override fun onCreate() { super.onCreate() VolleySingleton.preInit(this) // 后续再初始化SDK,此时Volley单例已就绪 MyCustomSDK.initialise(this) }
3. 系统线程资源耗尽
应用启动阶段若创建大量线程,可能导致系统无法分配新线程,Thread.nativeCreate会阻塞等待资源。
修复方案:
- 自定义Volley RequestQueue的线程池大小,减少默认线程数:
// 创建RequestQueue时指定线程池大小(默认是4,按需调整) val requestQueue = Volley.newRequestQueue(context, HurlStack(), 2)
- 排查应用其他模块的线程创建逻辑,避免启动阶段创建过多线程。
4. 锁竞争导致主线程阻塞
若allAPIsCall或Volley初始化过程中持有全局锁,且该锁被其他线程长时间占用,会导致主线程阻塞等待。
修复方案:
- 移除
ApiCalls.allAPIsCall中不必要的全局同步代码块; - 确保Volley相关操作不依赖其他耗时的同步初始化逻辑。
验证方法
- 使用Android Studio的Profile工具监控主线程耗时,定位初始化阶段的阻塞点;
- 开启StrictMode检测主线程的违规操作:
// 在MainApplication.onCreate中添加 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() .detectDiskWrites() .detectNetwork() .penaltyLog() .build());
内容的提问来源于stack exchange,提问作者Prashant Sharma

