在onDestroy()和GC之后,Android服务实例继续存在

时间:2015-12-08 20:40:32

标签: java android memory-leaks garbage-collection leakcanary

我创建了一个测试应用,看看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,对吧?但它仍然返回指定的值。为什么呢?

1 个答案:

答案 0 :(得分:0)

  

这个想法是,在销毁Service并调用GC之后,WeakReference应该返回null。

您似乎误解了WeakReference,或者至少我不清楚为什么您认为您提供的代码会表现出任何意外行为。如果您为某个对象WeakReference创建o,并且一段时间后GC确定o无法强烈访问,那么GC将清除WeakReference

您正在为WeakReference对象创建String,在源代码中以文字形式表示。如果Java使用String的实习版本 - 它很可能会这样做 - 那么它可能会选择将其视为始终强烈可达,以便永远不会清除引用对象。

因为你说要监视Service的清理,并且你提出了Service的子类,我倾向于认为你正在监视对象的清理创建了 WeakReference。这不是它的工作方式。

如果确实要监视Service的清理,则需要为服务对象创建WeakReference 。在您当前的代码中,拼写为new WeakReference(this)

另请注意,监视对象何时不能被强烈访问是ReferenceQueue s的目的。如果你创建一个ReferenceQueue并用它注册你的WeakReference,那么你可以看到弱引用被入队,而不是测试它的目标是否被清除。