【问题标题】:Android Service instance continue to exist after onDestroy() and GCAndroid Service 实例在 onDestroy() 和 GC 后继续存在
【发布时间】:2016-03-13 22:44:40
【问题描述】:

我创建了一个测试应用来查看 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,对吗?但它仍然返回分配的值。为什么?

【问题讨论】:

  • 我相信存在通过sWeakReference = new WeakReference("data") 对字符串文字"data" 的隐式硬引用。请改用sWeakReference = new WeakReference(new String("data"))。顺便说一下,对字符串进行弱引用的意图是什么?
  • 谢谢。你是对的。

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


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-04
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-03
    • 1970-01-01
    相关资源
    最近更新 更多