【问题标题】:Static singleton class memory leak in androidandroid中的静态单例类内存泄漏
【发布时间】:2014-11-12 08:42:10
【问题描述】:

我有一个扩展我的用户对象的静态单例类:

public class TestSingleton extends User{

    private static TestSingleton singletonInstance;

    private TestSingleton() {
    }

    public static TestSingleton getObj() {
        if (singletonInstance == null) {
            singletonInstance = new TestSingleton();
        }
        return singletonInstance;
    }
}

单例的目的是避免在我想在不同活动中使用我的用户对象时创建新实例:

TestSingleton test = new TestSingleton();
test.doSomthing();

并且在我的应用程序生命周期中将其写在一行上并只创建一次实例:

TestSingleton.getObj().doSomthing();

我的问题是:

这种使用静态单例是否会造成内存泄漏并保留对我使用单例的任何活动的引用?

使用安全吗?还是有更好的解决方案?

【问题讨论】:

  • 您确定它正在造成泄漏还是在询问我们是否会?据我所知,不会。除非User 持有对某些上下文的引用。
  • 请注意,您的单例目前不是线程安全的,请注意。
  • 你能用enum完成你需要的吗?
  • Activity 引用了您的单身人士,而不是相反。这意味着单例不会持有对任何Activity 的引用,但只有当所有持有对您的单例的引用的活动都被销毁时,单例才会被销毁
  • Fildor - 是的,我在问,User 只是一个 java 类,它的方法没有获取任何上下文或活动参数。

标签: java android memory-leaks


【解决方案1】:

这种使用静态单例是否会造成内存泄漏并持有引用 我使用单例的任何活动?

在 99.9% 的情况下不会,

Is it safe to use?

这取决于您所说的安全。例如,您的实现不是线程安全的。如果你从两个不同的线程调用 getObj() ,你可能会实例化 TestSingleton 两次。

 or there is a better solution?

有一个使用枚举的单例模式的实现。您可以在 Effective Java 上找到一个示例

【讨论】:

【解决方案2】:
A memory leak may happen when an object is stored in memory but cannot be accessed by the running code

对于单例,只创建一个对象。它仅在首次使用时创建。不可能存在内存泄漏。 只有当你想多线程使用它时,你必须同步实例(),这样对象才被创建一次。

并且 99.99% 的人确信不会有任何内存泄漏

【讨论】:

    【解决方案3】:

    是的,单例可能会导致内存泄漏,请阅读这篇文章:https://stackoverflow.com/a/13891253/1028256

    在 Android 生命周期中,可能会重新创建活动,并且您的单例可能会保留对旧活动实例的引用,从而防止它被垃圾收集。这意味着如果你保留这样的引用,你应该在单例中取消它们,在 Activity.onDestroy()

    仅供参考,当应用程序被销毁时,单例也可能被销毁,因此您不能依赖它。

    您可能需要考虑将数据永久保存在应用存储或应用程序对象中。

    【讨论】:

    • 引用您在回答中链接的帖子“因此,关键字 static 本身可能会导致内存泄漏,如果它引用 Activity 对象,因此在使用它时应该非常小心。”您可以改用应用程序上下文轻松解决此问题。
    【解决方案4】:

    如果您只需要User 的一个实例,则无需扩展它。你在TestSingleton 中所做的只是在User 类中进行。

    例如:

    public class User{
    
    private static User singletonInstance;
    
    private User() {
    }
    
    public static User getObj() {
        if (singletonInstance == null) {
            singletonInstance = new User();
        }
        return singletonInstance;
    }
    }
    

    更新:

    为了线程安全使用

    public synchronized static User getObj() {
        if (singletonInstance == null) {
            singletonInstance = new User();
        }
        return singletonInstance;
    }
    

    我认为在这种方法中你不需要考虑内存泄漏。

    【讨论】:

    • 问题是我的用户对象是源文件夹的一部分,其中包含多个对象,我有一个单例对象,比如用户对象,它位于服务器的 git 中,所以我想避免更改任何拉动的课程。我可以在我的单例类中使用同步,它会得到相同的效果吗?
    • 是的,你可以,这将获得相同的效果,你的代码将更可靠。实际上,“同步”的使用就像最佳实践一样,它将保证 100% 您永远不会获得超过一个实例。
    猜你喜欢
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    相关资源
    最近更新 更多