2015-01-06 65 views
4

我想測試Java WeakHashMap中類功能,併爲此事我寫了下面的測試:的Java WeakHashMap中類

public class WeakHashMapTest { 

public static void main(String args[]) { 
    Map<String, Object> weakMap = new WeakHashMap<>(); 
    String x = new String("x");  
    String x1 = new String("x1"); 
    String x2 = new String("x2"); 
    weakMap.put(x, x); 
    weakMap.put(x1, x1); 
    weakMap.put(x2, x2); 
    System.out.println("Map size :" + weakMap.size()); 
    // force all keys be eligible 
    x=x1=x2=null; 
    // call garbage collector 
    System.gc(); 
    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    System.out.println("Map size :" + weakMap.size()); 
    System.out.println("Map :" + weakMap); 
} 

}  

運行下課後WeakMapTest我感到不高興得到以下的輸出:

gc之前的地圖:{x = x,x1 = x1,x2 = x2} gc後的地圖:{x = x,x1 = x1,x2 = x2}

當我預計地圖將爲空時。

也就是說,垃圾收集器沒有做它的工作。但爲什麼?

回答

5

WeakHashMap將無法​​再通過垃圾回收器回收密鑰。

執行注意事項: WeakHashMap中的值對象由普通強引用保存。因此,應該注意確保值對象不直接或間接強烈地引用它們自己的密鑰,因爲這將防止密鑰被丟棄。

但是,由於您使用了密鑰本身作爲值,因此該值仍然可以很好地訪問,這意味着垃圾回收器無法回收密鑰。

但是,如果您使用其他對象作爲值,那麼對鍵的唯一引用將是鍵本身。

weakMap.put(x, new Object()); 
weakMap.put(x1, new Object()); 
weakMap.put(x2, new Object()); 

然後,在清除變量和調用垃圾回收器,你已經做了之後,我得到的輸出:

Map size :3 
Map size :0 
Map :{} 

即使調用System.gc()不保證垃圾收集器運行,它看起來像在這裏運行。

+0

當我使用上面演示的代碼和新的Object()時,它確實工作正常,但是當我想要類似Set實現時,鍵和值具有相同的引用時,我該怎麼辦? –

+0

我不知道任何JDK提供的類會爲'Set's提供'WeakHashMap'類行爲。 – rgettman

+0

@IgalIsra然後你可能需要[番石榴的干擾者](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Interners.html#newWeakInterner())。 – maaartinus

1

System.gc()實際上是一個建議來運行垃圾回收器。有沒有保證的方式垃圾收集器運行。

+0

[文檔另有其他說明](http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#gc()):「控件從方法調用返回時, Java虛擬機已盡最大努力從所有丟棄的對象中回收空間。「 – gknicker

+0

參見例如http://stackoverflow.com/questions/66540/when-does-system-gc-do-anything,http://stackoverflow.com/questions/2414105/why-is-it-bad-practice-to-call- system-gc和其他幾個來源。 –

+0

更具體地說,請參閱http://bugs.java.com/view_bug.do?bug_id=6668279,這是針對文檔的錯誤。 –