实例变量是否保持对静态变量的强引用会造成内存泄漏?

时间:2015-07-10 05:43:38

标签: java memory-leaks garbage-collection

请考虑以下代码:

public class Leaky {

    public static LongLive instance = new LongLive();

    static class LongLive {
        public void create() {
        }
    }

    static class Victim {

        final LongLive factory;

        public Victim() {
            /** Hold strong reference to static instance */
            System.out.println("Create new child..");
            factory = instance;
        }

        @Override
        protected void finalize() throws Throwable {
            System.out.println("About to get gc-ed?");
            super.finalize();
        }
    }

    static void sleep(int sec) {
        try {
            Thread.sleep(sec * 1000L);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; ++i) {
            final Victim c = new Victim();
            System.gc();
            sleep(1);
        }
    }
}

根据我的理解,任何Victim对象都不应该被gc-ed,因为它保留了对instance对象的强引用,该对象只要程序运行就存在。但是,我确实看到打印出“即将获得gc-ed”。有人能帮我解释一下吗?

1 个答案:

答案 0 :(得分:2)

Victim得到gc-ed因为没有引用指向它们,所以它们可以被安全地gc-ed,因为没有人能够再次使用它们(在每次迭代后你都会失去对它的引用)最后Victim因为您将其分配给for循环内的变量。

他们所指的并不重要。重要的是谁指向他们。

内存泄漏的典型情况是堆栈的这种实现。

public class Stack {
    Object[] st = new Object[100];
    int top;

    public void push(Object o) {
       // Not checking boundaries for simplicity.
       st[top++] = o;
    }

    public Object pop() {
       return st[--top];
    }

}

请注意,弹出后,存储在数组中的元素仍然存在,除非您将位置设置为null或其他元素覆盖它们,否则这些元素将不会被gc-ed