2015-07-10 17 views
0

考虑下面的代码:对静态变量保持强引用的实例变量是否会造成内存泄漏?

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”。任何人都可以帮我解释一下吗?

+6

你拥有了它倒退,对象将永远不会被垃圾收集,只要在其他地方有强烈的参考。这个对象本身所引用的内容并不重要。 – Kon

+1

@Kon:啊,明白了。谢谢! – Chan

回答

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