Activity启动时Context.getApplicationInfo()空指针问题排查与修复
问题描述
我们的应用中某Activity出现大量崩溃,尝试通过所有可能入口(深度链接、常规用户操作等)启动该Activity均无法复现,且已确认未在onCreate()之前调用findViewById(该操作曾引发其他同类崩溃)。
崩溃栈1
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:191) at android.app.FragmentManagerImpl.getTargetSdk(FragmentManagerImpl.java:2975) at android.app.FragmentManagerImpl.attachController(FragmentManagerImpl.java:2964) at android.app.FragmentController.attachHost(FragmentController.java:89) at android.app.Activity.attach(Activity.java:8016) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3751) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3977) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:109) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2374) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loopOnce(Looper.java:233) at android.os.Looper.loop(Looper.java:344) at android.app.ActivityThread.main(ActivityThread.java:8248) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:589) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1071)
崩溃栈2
Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{MerchantProfileDetailsActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3651) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3808) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:103) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2221) 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 android.app.ActivityThread.main(ActivityThread.java:7952) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
疑问
- 如何关联崩溃栈中的所有线程信息?推测是崩溃时各线程的状态。
- 引发上述NPE的可能原因有哪些?
- 从栈信息能否确定崩溃发生在
onCreate()代码执行之前?
崩溃本质上由ActivityThread.handleLaunchActivity()和ActivityThread.performLaunchActivity()抛出,且完整栈中未出现应用自有代码,目前不知如何修复该问题,恳请提供解决思路。
解答
1. 关联崩溃时的线程信息
- 主流崩溃收集工具(如Firebase Crashlytics、Bugly)默认会捕获崩溃发生时所有线程的调用栈,在崩溃详情页的「Threads」板块可查看每个线程的ID、名称、状态(RUNNABLE/BLOCKED等)及完整调用栈。
- 若自行实现崩溃捕获,需在
UncaughtExceptionHandler中调用Thread.getAllStackTraces()遍历所有线程,记录每个线程的状态和调用栈信息,以此关联崩溃时的多线程状态。
2. 引发该NPE的可能原因
- Activity上下文初始化异常:Activity在
attach阶段,ContextWrapper的底层mBase还未正确赋值,就被调用了getApplicationInfo()。常见于自定义Activity基类提前执行依赖Context的逻辑,或第三方框架通过反射篡改了Activity初始化流程。 - FragmentManager关联Context为空:从调用栈看,崩溃触发于
FragmentManagerImpl.getTargetSdk(),该方法依赖Activity的Context获取ApplicationInfo。若在Activity attach前就初始化Fragment相关逻辑,或第三方Fragment库存在兼容问题,会导致FragmentManager关联的Context被置空。 - 系统/ROM兼容性问题:不同Android版本的
ActivityThread、FragmentManager实现存在差异,部分厂商定制ROM修改了系统源码,可能导致Activity初始化流程中Context未正常赋值。 - 多线程干扰:后台线程若在Activity初始化过程中意外访问未完全初始化的Activity实例,可能导致Context被异常置空或未赋值。
3. 确定崩溃发生在onCreate()之前
从第一个崩溃栈的调用链可明确:ActivityThread.performLaunchActivity() → Activity.attach() → FragmentController.attachHost() → FragmentManagerImpl.attachController() → FragmentManagerImpl.getTargetSdk()。而Activity.onCreate()是在performLaunchActivity()中Activity.attach()执行完成后才调用的,因此崩溃确实发生在onCreate()代码执行之前。
修复思路
- 排查自定义Activity基类:检查该Activity继承的基类,确认
attachBaseContext()、onAttach()等生命周期方法中是否提前执行了依赖Context的逻辑(如初始化第三方SDK、Fragment操作),确保所有需Context的代码在onCreate()之后或attachBaseContext()完成后执行。 - 检查第三方库:排查与Fragment、Activity生命周期相关的第三方框架(如路由、埋点、UI库),看是否存在在Activity初始化阶段提前调用FragmentManager的情况,可暂时禁用可疑库验证崩溃是否消失。
- 兼容特定系统/ROM:收集崩溃设备的系统版本、厂商信息,若崩溃集中在特定设备,针对这些设备做兼容处理,比如延迟Fragment相关初始化,或使用系统兼容API。
- 补充崩溃信息:在崩溃捕获中添加线程信息、设备参数、启动Activity的Intent数据,排查是否存在携带特殊参数的Intent触发崩溃。
- 模拟极端场景复现:尝试模拟低内存(开启开发者选项「不保留活动」)、快速连续启动Activity、后台启动Activity等极端情况,看能否触发崩溃。
内容的提问来源于stack exchange,提问作者Vikas Pandey
相关产品推荐
相关产品推荐

