写入本地存储时触发Check failed: receiver != nullptr virtual(SIGABRT)崩溃排查
排查Gson序列化触发ART Native崩溃的思路
这个ART层的Check failed: receiver != nullptr virtual崩溃通常和反射调用时对象实例无效、类加载异常或者ART runtime的兼容性问题有关。结合你提到代码之前正常运行,重点应该放在最近的变更点上,下面是一步步的排查思路:
先确认Identity对象实例的有效性
在调用gson.toJson(identity)之前,添加调试日志打印对象的状态:AppLog.i(TAG, "Identity instance: ${identity.hashCode()}, deviceId: '${identity.deviceId}', environment: '${identity.environment}'")确保
identity不是null,且两个字段都有正常赋值。虽然你代码里显式创建了实例,但如果最近修改过Identity类的构造方法(比如改成私有、添加了异常逻辑),可能会导致实例内部状态异常。检查Gson依赖或配置的变更
- 确认最近有没有升级Gson版本:某些Gson版本在特定Android系统上存在反射兼容性问题,比如旧版本Gson和Android 10+的ART规则冲突。可以临时回退到之前正常运行的Gson版本测试。
- 检查GsonBuilder的配置:你当前的代码没有启用
excludeFieldsWithoutExposeAnnotation(),但如果最近添加/移除过这个配置,或者修改了@Expose注解的使用,可能引发反射逻辑的变化。
排查编译优化(R8/ProGuard)的变更
Native崩溃很可能是混淆导致Gson反射时找不到类或字段:- 检查最近有没有修改ProGuard/R8规则:
Identity类的@SerializedName注解如果被混淆,会导致Gson反射逻辑异常。确保规则里保留了该类的注解和字段:-keep class com.your.package.Identity { @com.google.gson.annotations.SerializedName <fields>; @com.google.gson.annotations.Expose <fields>; } - 临时关闭R8混淆,测试是否还会崩溃,以此确认是否是混淆导致的问题。
- 检查最近有没有修改ProGuard/R8规则:
检查ART运行时相关的配置变更
- 确认最近有没有修改
minSdkVersion或targetSdkVersion:不同Android版本的ART实现有差异,比如某些Android 7.x/8.x版本的ART在处理反射调用空对象时会触发这类崩溃。 - 检查是否开启了新的编译选项:比如
-Xlint或其他代码优化开关,可能影响类的加载逻辑。
- 确认最近有没有修改
隔离测试序列化逻辑
把序列化代码从文件操作逻辑中剥离出来,单独测试:fun testSerialization() { val identity = Identity().apply { deviceId = "test-device-id" environment = "test-env" } val gson = GsonBuilder().setPrettyPrinting().create() val json = gson.toJson(identity) AppLog.i(TAG, "Serialized json: $json") }如果单独测试不会崩溃,说明问题出在文件操作和序列化的交互上(比如内存不足、线程冲突导致对象被意外回收);如果仍然崩溃,就可以把问题锁定在Gson和
Identity类的交互上。获取更完整的Native崩溃日志
用adb logcat -v long捕获完整的崩溃堆栈,除了你提供的开头和结尾,中间的调用栈会显示是Gson的哪个方法触发了ART崩溃(比如反射获取字段、调用 getter 时),这能帮你精准定位问题点。检查
Identity类的最近变更
确认最近有没有修改Identity类:- 是否添加了新的字段(尤其是非基本类型字段)?
- 是否修改了字段的访问修饰符(比如从
public改成internal)? - 是否添加了自定义的getter/setter方法,且方法内部有异常逻辑?
内容的提问来源于stack exchange,提问作者andrewedgar
相关产品推荐
相关产品推荐

