2012-10-14 23 views
1

考慮下面的Java代碼這些物體是否會被GC收集?

public class PlayerView implements IPlayerListener 
{ 
    public Player player; 

    public PlayerView() 
    { 
     player = new Player(); 
     player.listener = this; 
    } 

    public void onPlayerEvent() 
    { 

    } 
} 

public class Player 
{ 
    public IPlayerListener listener; 

    public void foo() 
    { 
     //do something then 
     if(this.listener != null) 
     { 
      this.listener.onPlayerEvent(); 
     } 

    } 
} 

public interface IPlayerListener 
{ 
    public void onPlayerEvent(); 
} 

在這裏,我有一個PlayerView和播放器。玩家需要向PlayerView報告事件,所以我創建了一個名爲IPlayerListener的接口,該接口可以爲PlayerListener對象提供一個引用來報告事件。

(我知道在Java中,這不是創建活動的最佳方式,但我並不真的需要「許多聽衆」使用默認「的addEventListener」模式)

問題1:當PlayerView object設置爲null,PlayerView和Player對象是否都會被GC收集?

如果是,那麼請繼續下面的代碼

public class PlayerView implements IPlayerListener, IPlaylistListener 
{ 
    public Player player; 

    public PlayerView() 
    { 
     player = new Player(); 
     player.listener = this; 
     player.playlist = new Playlist(); 
     player.playlist.listener = this; 
    } 

    public void onPlayerEvent() 
    { 

    } 

    public void onPlaylistEvent() 
    { 

    } 
} 

public class Player 
{ 
    public Playlist playlist; 
    public IPlayerListener listener; 

    public void foo() 
    { 
     //do something then 
     if(this.listener != null) 
     { 
      this.listener.onPlayerEvent(); 
     } 

    } 
} 

public class Playlist 
{ 
    public IPlaylistListener listener; 

    public void bar() 
    { 
     //do something then 
     if(this.listener != null) 
     { 
      this.listener.onPlaylistEvent(); 
     } 
    } 
} 

public interface IPlayerListener 
{ 
    public void onPlayerEvent(); 
} 

public interface IPlaylistListener 
{ 
    public void onPlaylistEvent(); 
} 

在這裏,我增加了第三級,Playlist類,其播放器也有一個播放列表對象的引用。 另外播放列表應該有一個監聽器/觀察者。在這種情況下,PlayerView也是播放列表監聽器。

問題2:當PlayerView對象設置爲null時,這些對象是否會被GC收集?

如果答案#2是NO,那麼請繼續

public class PlayerView implements IPlayerListener, IPlaylistListener 
{ 
    public Player player; 

    public PlayerView() 
    { 
     player = new Player(); 
     player.listener = this; 
     player.playlist = new Playlist(); 
     player.playlist.parentPlayer = player; 
    } 

    public void onPlayerEvent() 
    { 

    } 

    public void onPlaylistEvent() 
    { 

    } 
} 

public class Player 
{ 
    public Playlist playlist; 
    public IPlayerListener listener; 

    public void foo() 
    { 
     //do something then 
     if(this.listener != null) 
     { 
      this.listener.onPlayerEvent(); 
     } 

    } 
} 

public class Playlist 
{ 
    public Player parentPlayer; 

    public void bar() 
    { 
     //do something then 
     if(this.parentPlayer != null) 
     { 
      if(this.parentPlayer.listener != null) 
      { 
       if(this.parentPlayer.listener instanceof IPlaylistListener) 
       { 
        ((IPlaylistListener) this.parentPlayer.listener).onPlaylistEvent(); 
       } 
      } 
     } 
    } 
} 

public interface IPlayerListener 
{ 
    public void onPlayerEvent(); 
} 

public interface IPlaylistListener 
{ 
    public void onPlaylistEvent(); 
} 

在這裏,我切換與父玩家一個參考playlistListener參考,而不是直接調用playlistListener,檢查如果playerListener也一個PlaylistListener(或兩個接口可以合併爲一個)

問題3:以前的代碼是否能解決問題並收集所有對象?

或者我應該更好地使用第二個代碼塊,並在PlayerView對象中找到合適的時間(就像PlayerView對象從其父視圖中移除之前一樣)並至少調用「player.playlist.listener = null;」。

+0

順便說一句,在播放列表類中,我需要一個對其父Player對象的引用。我應該用WeakReference 代替嗎? –

回答

4

重要的是要認識到,從理論上來說,不可能預測什麼時候物體實際上會被垃圾收集。更具體地說,將字段設置爲null不會導致它被收集。相反,它可能會導致它無法訪問,因此合格收集垃圾。這意味着它可能在可能收集在一些下面的GC運行,但不一定是下一次運行。 (而且注意,甚至稱System.gc()不能保證使符合條件的物體被收集的JVM是自由忽略gc()電話。)

注:可達性是所有對象是否仍然可以通過一些活動線程訪問。如果一個線程可以跟隨一個引用鏈來達到某個對象,那麼它就是可達的。當然,鏈需要以線程可以訪問的引用變量開始;例如線程堆棧上的靜態變量或局部變量或參數。


所以爲了您的具體問題:

問題1:當PlayerView對象設置爲空,將兩個PlayerView和Player對象被GC回收?

該代碼不會創建PlayerView實例或具有可能爲零的PlayerView變量。我還注意到Player和PlayerView對象指向對方。該參考週期不直接影響可達性。雖然這意味着如果任何一個對象都可以訪問,那麼兩者都是。

所以,如果我們假定只有一個PlayerView變量...並沒有Player變量...然後分配null的變量會導致兩個對象變得不可達,因此有資格領取。

問題2:當PlayerView對象設置爲null時,這些對象是否會被GC收集?

同樣,用相同的警告,當最後到達參考PlayerView被清零(或者當它變得不可訪問),所有三個對象將有資格被收集。


幾點建議:

  1. 你可能過分擔心何時以及如何得到的對象回收。它很可能沒有絲毫的區別。
  2. 明確地忽略導致它們被收集的事物通常是浪費時間。
  3. 有沒有必要擔心Java中的引用週期。 Java GC不基於引用計數,並且不需要中斷週期以使GC工作。
+0

*並且請注意,即使調用System.gc()也會保證能夠收集符合條件的對象。*缺少否定嗎? –

+0

我糾正了......謝謝。 –

+0

我知道設置和對象引用null不會導致收集對象,我的問題應該是「這些對象是否有資格收集」,正如您所說的。 –

相關問題