【发布时间】:2017-06-01 18:06:54
【问题描述】:
我在 Google Play 中有一堆痕迹,其中应用程序类的静态成员似乎为空。
我发现的所有相关帖子都是关于存储数据的,但这些变量不是数据,它们是 3rd 方 SDK 实例或其他与应用程序一起使用单例模式的关键对象。
Activity 类中使用的数据存储在数据库中,并且没有使用静态引用。
这些痕迹根本不会报告给 Fabric,这很奇怪,因为它是在 Application onCreate 方法中初始化的。
当FirebaseMessagingService onMessageReceived 方法被触发时,跟踪表明静态变量为空,我需要将消息传递给第 3 方 SDK,但由于该实例为空,因此应用程序崩溃。
仅在 Android OS 6.0 中看到的痕迹
对于如何处理这个操作系统版本如此激进地清空静态成员,有什么解决方案吗?
谢谢。
这是我使用的最小示例代码:
应用类:
@Override
public void onCreate() {
Engine.init();
}
引擎类:
private static Engine sInstance;
private 3rdParty m3rdParty;
private Engine() {
m3rdParty = new 3rdParty();
}
public static void init() {
if (sInstance == null) {
sInstance = new Engine();
}
}
public static onMessageReceived(RemoteMessage remoteMessage) {
sInstance.m3rdParty.onMessageReceived(remoteMessage);
// Above line crashes with NPE, sEngine or m3rdParty is never set to null in code
}
扩展 FirebaseMessagingService:
public void onMessageReceived(RemoteMessage remoteMessage) {
Engine.onMessageReceived(remoteMessage);
}
【问题讨论】:
-
Android 不会清空静态字段。您能否发布您的
Application课程以及这些单例如何初始化的详细信息? -
在一个地方看起来你的单身人士被命名为
sEngine;在另一个,sInstance。这可能是问题吗? -
你的单例不是线程安全的,但如果你只在主线程中访问它就不需要了。您是否从发布的代码中删除了任何异步内容?
-
@KevinKrumwiede 抱歉打错了,你能告诉我更多关于这个线程安全的信息吗?
-
因为
sInstance不是final或volatile,所以如果你设置在一个线程(这里是主线程)中,在另一个线程中读取,另一个线程不是保证看到你写的值。但是不是线程安全的代码几乎总是可以工作,这就是线程安全漏洞难以识别的原因。
标签: android android-6.0-marshmallow low-memory