You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native调用自定义Native模块触发ANR问题排查求助

排查与修复React Native自定义模块触发的Volley相关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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 16:30:44