Activity持有对Singleton的引用会导致内存泄漏?

4
如果我有以下这样的代码:
public class MyActivity extends Activity 
{

private SingletonClass singletonInstance;

...

@Override
protected void onCreate(Bundle savedInstanceState) 
{
    singletonInstance = SingletonClass.getInstance();
}

...
}

我的理解是,该Activity将保持活动状态,因为它具有对静态实例的引用,因此无法被垃圾回收。然而,在我的应用程序中,这似乎并没有给我带来任何问题。我是否不理解GC,或者这确实泄漏了内存,我应该避免保留对我的单例类的引用?


3
您的代码是正确的。在您提供的代码片段中,没有任何可能导致泄漏的情况。如果单例持有对MyActivity的引用,则可能会导致泄漏。 - Blackbelt
我认为如果你将singletonInstance声明为静态的,那么这种情况可能会发生... 对于你的Activity,singletonInstance只是SingletonClass的一个实例。请记住,不存在“静态实例”这样的东西,实例只是一个类,它的静态性是由你在作用域中声明的方式决定的。对于MyActivity,即使在SingletonClass内部引用相同的对象/实例,singletonInstance也不是静态的... - Martin
你能具体说明下你认为哪里出现了泄漏吗?你有看到logcat信息吗? - Yojimbo
我没有任何理由担心(除了我的理解)。我困惑的是活动对象是否会在应用程序的整个生命周期中保持活动状态。然而,我认为我误解了GC的工作方式。活动对象未被单例引用,因此在更改活动时将被GC回收。 - Luke Deighton
2个回答

1
我一直在使用Square的LeakCanary来检测Android应用中的内存泄漏,发现一个Activity存在内存泄漏问题,原因是由一个静态单例对象持有了该Activity的引用。
我的Activity与Q中的结构相同,它引用了一个Presenter类的单例对象,但该引用并非静态。
public MyActivity extends Activity {
  private MyPresenter mPresenter;
  ...
  onCreate() {
     mPresenter = MyPresenter.getInstance()
     ...
  }
}
..
public class MyPresenter { // Different class
 private static MyPresenter mInstance;
... singleton code ...
}

我阅读了这个链接,我认为它很有道理。http://www.javaworld.com/article/2071737/core-java/plug-memory-leaks-in-enterprise-java-applications.html

一旦单例类被实例化,它将在应用程序的生命周期内保留在内存中。其他对象也会对其有一个活动引用,因此永远不会被垃圾回收。

建议:避免从长期存在的对象引用对象。如果无法避免这种用法,则使用弱引用,这是一种不会阻止对象被垃圾回收的对象引用类型。


1

我已经研究了你的疑问,并确认我的答案:

如果你将singletonInstance声明为静态的,这种情况就会发生。对于你的Activity来说,singletonInstance只是SingletonClass的一个实例。请记住,"静态实例"并不存在,实例只是给定类的对象,使其静态的是你在作用域内声明它的方式。对于MyActivity来说,singletonInstance不是静态的,即使在SingletonClass内部你正在引用同一个对象/实例,并将其声明为静态。

这样,你的Activity就可以被GC清理而没有问题。我在Android上有一个类似的实现,它涉及到一个Service,在数百个小时内运行良好,没有任何内存或性能问题......

此致敬礼


谢谢您的解释,现在我明白了! - Luke Deighton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接