2015-07-10 16 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