2012-08-01 68 views
4
class Beta { } 

class Alpha { 
static Beta b1 ; 
Beta b2; 
} 

public class Tester { 

public static void main(String[] args) { 

    Beta b1 = new Beta(); 
    Beta b2 = new Beta(); 
    Alpha a1 = new Alpha(); 
    Alpha a2 = new Alpha(); 

    a1.b1 = b1 ; 
    a1.b2 = b1 ; 
    a2.b2 = b2 ; 

    a1 = null ; 
    b1 = null; 
    b2 = null; 

    System.out.println(" Line 1 " + " a1 " + a1.b1); 
    System.out.println(" Line 2 " + " a1 " + a1.b2); 
    System.out.println(" Line 3 " + " a2 " + a2.b2); 
    System.out.println(" Line 4 " + " a1 " + a2.b1); 
    System.out.println(" Line 5 " + " b1 " + b1); 
    System.out.println(" Line 6 " + " b1 " + b2); 

    } 

} 

我不知道爲什麼在上面的程序中只有a1對象可用於垃圾收集。我期待a1,b1和b2被垃圾收集器收集。在java中的垃圾收集示例?

正如您所見,a1,b1和b2被設爲NULL,因此這使得對象可用於垃圾收集。如果任何線程或引用變量對象爲NULL或無法訪問,則應由垃圾收集器收集。

有人能幫助我更好地瞭解上述計劃的細微之處嗎?感謝您的幫助。

+4

您不能在Java中「創建對象爲空」。不過,您可以將_reference_對象刪除。無論如何,除非使用弱引用或類似方法,否則不能真正「觀察」Java中的垃圾回收。 – 2012-08-01 14:32:59

+2

你是怎麼知道b1和b2不是垃圾收集的? – Byter 2012-08-01 14:37:36

回答

7

因爲仍然存在由於下面的線引起的對象指向的對象。

a1.b1 = b1 ; 
a1.b2 = b1 ; 
a2.b2 = b2 ; 

假設這樣的:

b1--->BetaObj1 
    b2---BetaObj2 
    a1---> AlphaObj1 
    a2---> AlphaObj2 

a1.b1點B1,這意味着,存在參照BetaObj1 a1.b2點B1,這意味着,存在另一個參考BetaObj1

(此時有3個引用BetaObj1)

a2.b2點B2這意味着,有參照BetaOBj2

(此時有2個引用BetaObj2)

a1=null;使得AlphaObj1獲GC

b1=null;使得BetaObj1引用計數爲2,所以這個對象是不符合GC

b2=null;品牌BetaObj2引用計數爲1,因此此對象不適用於GC。

+0

我喜歡你的答案,儘管與MR Daniel Fischer在本頁底部的答案有點矛盾。假設b1 ----> BetaObj1,a1.b1 ----> BetaObj1和a1.b2 ----> BetaObj1 – MKod 2012-08-02 13:57:07

+0

。當a1 = null時,哪個引用連接將被剪切到BetaObj1,是a1.b1還是a1.b2或b1。我期待你的答案只是b1而不是a1.b1和a1.b2。當我執行a1.b2時拋出NullPointerException,而同樣的事情MR Fischer說。 – MKod 2012-08-02 13:57:42

+0

Fischer先生正在談論靜態b1實例變量。我知道一個靜態實例變量不需要實例來訪問。但是他爲什麼說只是因爲b1是靜態的a1.b1將永遠存在(可能我在最後一點是錯的,但我不能比菲捨爾先生對靜態所說的要多得多)。你能幫我理解這個概念嗎?我想我只是非常接近理解垃圾收集的概念。 – MKod 2012-08-02 13:57:48

1
  • b2不適用於GC,因爲還有一個參考a2.b2
  • b1不適用於GC因爲Alpha.b1持有對它的引用(Alpha.b1是靜態的,不要困惑,因爲它的設置使用a1.b1
1

你應該得到一個NullPointerException這裏:

System.out.println(" Line 1 " + " a1 " + a1.b1); 
System.out.println(" Line 2 " + " a1 " + a1.b2); 

此時,a1已被設置爲null,因此訪問其成員b2無法工作,因爲它不再引用對象。 (訪問靜態b1作品,因爲這不僅需要一流的,不是一個實例。)

正如你看到的A1,B1和B2作了NULL因此這是使對象可用於垃圾收集。

不,你要設置這些對象的一些引用null,而對這些對象的其他引用存在,因爲是b1b2的情況下,這些對象目前還無法收集。

1

有幾個誤解這裏

  • 的GC,只有當它需要運行。爲了更頻繁地執行GC,他們將不需要進行工作。
  • a1.b1實際上是Alpha.b1作爲實例並不重要,甚至可以是null使用al.b1是明顯混淆。
  • a1.b2應拋出NullPointerException,因爲a1的值爲null
  • Alpha.b1已設置但未在任何地方清除,因此它引用的對象不符合清理條件。其他對象可以清理乾淨,但不需要明確地調用System.gc();,它是非常不可能的,它需要在您可能期望的點運行。
  • a1被清除,但a2是不是這樣就不會被清理(直到方法返回)
0

垃圾收集實例

public class GarbageCollection { 

    public static void main(String s[]) throws Exception { 
      Runtime rs = Runtime.getRuntime(); 
      System.out.println("Free memory in JVM before Garbage Collection = "+rs.freeMemory()); 
      rs.gc(); 
      System.out.println("Free memory in JVM after Garbage Collection = "+rs.freeMemory()); 
     } 
} 

程序的輸出:

垃圾收集前的JVM中的可用內存= 62767488

垃圾收集後的JVM中的空閒內存= 62854120