我创建了一个测试应用程序来查看 Android 的服务是否被正确回收。
我创建了一个服务,它只做一件事:保存对象的 WeakReference。这个想法是,在Service被销毁并调用GC之后,WeakReference应该返回null。这是我的服务:
package com.example.test.serviceleaktest;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import java.lang.ref.WeakReference;
public class MyService extends Service {
public static WeakReference sWeakReference = new WeakReference(null);
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
sWeakReference = new WeakReference("data");
Log.d("asdf", "MyService started");
return START_NOT_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
Log.d("asdf", "MyService created");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("asdf", "MyService destroyed");
}
}
我使用 Context.startService() 启动服务并使用 Context.stopService() 停止它。 LogCat 确认调用了 onDestroy()。然后我进行 GC(从 LeakCanary 复制的代码):
Runtime.getRuntime().gc();
Thread.sleep(100);
System.runFinalization();
此时,我假设 sWeakReference.get() 应该返回 null,对吧?但它仍然返回指定的值。为什么?
最佳答案
The idea is, after the Service is destroyed and GC is called, the WeakReference should return null.
您似乎误解了WeakReference
,或者至少我不清楚为什么您认为您提供的代码表现出了任何意外的行为。如果您创建一个指向某个对象o
的WeakReference
,并且一段时间后GC确定o
不是强可达的,那么GC将清除WeakReference
。
您正在创建一个指向String
对象的WeakReference
,该对象在源代码中表示为文字。如果 Java 使用该 String
的内部版本(它很可能会这样做),那么它可能会选择将其视为始终强可达,以便引用对象永远不会被清除。
由于您说您想要监视 Service
的清理,并且您提供了 Service
的子类,因此我倾向于认为您正在监视创建弱引用
的对象的清理。这不是它的工作方式。
如果您确实想要监视Service
的清理,那么您需要创建一个到服务对象的WeakReference
。在您当前的代码中,其拼写为 new WeakReference(this)
。
另请注意,监视对象何时不再可强访问是 ReferenceQueue
的目的。如果您创建一个 ReferenceQueue
并向其注册您的 WeakReference
,那么您可以监视要排队的弱引用,而不用测试其目标是否已清除。
关于java - Android Service 实例在 onDestroy() 和 GC 之后继续存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34165622/