【问题标题】:Java memory leaks understandingJava内存泄漏的理解
【发布时间】:2013-06-04 16:33:06
【问题描述】:

我已经询问过memory leaks on Android,但我还不太了解内存泄漏。现在我必须保存PhoneStateListener 收到的一些数据。单例模式很方便,因为我应该保证只有一个实例存在。

public class PhoneStateInfo {

    /** -1 until the first reception */
    private int mCid = -1;
    /** -1 until the first reception */
    private int mLac = -1;
    /** 0 until the first reception */
    private int mMcc;
    /** 0 until the first reception */
    private int mMnc;
    // And so on...

    private static PhoneStateInfo INSTANCE = new PhoneStateInfo();

    public static PhoneStateInfo getInstance() {
        return INSTANCE;
    }

    private PhoneStateInfo() {}

    /**
     * Reverts the single instance to its initial state
     * But if I have 10 or 20 fields which have various default values, it will be easy to forget something
     */
    void clear() {
        mCid = -1;
        mLac = -1;
        mMcc = 0;
        mMnc = 0;
        mRssi = -1;
        mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
        mDeviceId = null;
        mSubscriberId = null;
        mPhoneNumber = null;
    }

    /**
     * Reverts the single instance to its initial state
     * Short and clear
     */
    static void clearInstance() {
        INSTANCE = null; // If I delete this line, memory leaks will occur
        // because the old reference is left alive will not be garbage-collected
        INSTANCE = new PhoneStateInfo();
    }
}

请参阅clear()clearInstance() 方法。我的 cmets 在那里正确吗?

【问题讨论】:

  • 恕我直言,使用public enum PhoneStateInfo { INSTANCE; 要简单得多。你不需要销毁和重新创建这个类,你有一个claer(); 方法。
  • @PeterLawrey,谢谢。我还在《Effective Java》一书中读到了enum 模式。

标签: java memory-leaks static singleton


【解决方案1】:
 INSTANCE = null; // If I delete this line, memory leaks will occur
 // because the old reference is left alive will not be garbage-collected
 INSTANCE = new PhoneStateInfo();

这不是真的。

在将字段分配给新值之前,您不必将其设置为 null。您可以使用新值覆盖它。

如果没有新值,您可能希望将其设置为 null(以摆脱不再需要的实例并让垃圾收集器处理它)。

但即使你没有,我也不会称之为“内存泄漏”,因为它只有一个实例,因此非常有限。即使未使用,内存消耗也不会随着时间的推移而逐渐变大,这通常会导致“泄漏”。

【讨论】:

    【解决方案2】:
    static void clearInstance() {
        INSTANCE = null; // If I delete this line, memory leaks will occur
        // because the old reference is left alive will not be garbage-collected
        INSTANCE = new PhoneStateInfo();
    }
    

    该评论不正确。第一行基本上什么都不做。您将 INSTANCE 更改为不再指向旧的 PhoneStateInfo,但分配新的 PhoneStateInfo 也完成了使其不再指向旧的相同的任务!

    您无法确定旧的 PhoneStateInfo 是否会被垃圾收集。如果某处的另一段代码创建了对它的引用,则在该引用也消失之前,它不符合收集条件。

    【讨论】:

      【解决方案3】:

      对于纯 java 程序,您的 cmets 不正确。

      无需为对象设置null 即可将其标记为可用于GC。

      但如果您的程序使用自定义ClassLoadersWeakReferenceThreadLocals,它可能会泄漏。

      【讨论】:

        最近更新 更多