Java内存漏洞了解

时间:2013-06-04 16:33:06

标签: java memory-leaks static singleton

我已经问过memory leaks on Android但我还不知道内存泄漏。现在我必须保留PhoneStateListener收到的一些数据。 Singleton模式派上用场,因为我应该保证只存在一个实例。

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()方法。我的评论是否正确?

3 个答案:

答案 0 :(得分:3)

 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(去掉你不再需要的实例,让垃圾收集器得到它)。

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

答案 1 :(得分:1)

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将被收集垃圾,你不能确定这里。如果某个地方的另一段代码创建了对它的引用,那么在该引用也消失之前它不符合收集条件。

答案 2 :(得分:1)

对于普通的java程序,您的注释不正确。

无需为对象设置null以便为GC标记它。

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