1

我创建了一个测试应用程序来查看 Android 的服务是否被正确回收。

我创建了一个服务,它做一件事:持有一个对象的弱引用。这个想法是,在 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,对吗?但它仍然返回分配的值。为什么?

4

1 回答 1

0

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

您似乎误解了WeakReferences,或者至少我不明白为什么您认为您提供的代码表现出任何意外行为。如果你创建了一个WeakReference对象o,一段时间后 GC 确定它o不是强可达的,那么 GC 将清除WeakReference.

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

既然你说你想监视 a 的清理Service,并且你提出了 的一个子类Service,我倾向于认为你假设你正在监视创建的对象的清理WeakReference。这不是它的工作方式。

如果你确实想对监控进行清理Service,那么你想创建一个WeakReference 服务对象。在您当前的代码中,将拼写为new WeakReference(this).

另请注意,监视对象何时不再是强可达性是ReferenceQueues 的目的。如果你创建一个ReferenceQueue并注册你WeakReference的,那么你可以观察弱引用是否入队,而不是测试它的目标是否被清除。

于 2015-12-08T20:54:52.323 回答