2010-07-28 67 views
3

我正在根據here的說明使用LinkedHashMap來實現一個簡單的緩存。我使用下面的代碼:我可以通過它佔用的內存量限制HashMap嗎?

public class Cache extends LinkedHashMap { 
    private final int capacity; 

    public Cache(int capacity) { 
    super(capacity + 1, 1.1f, true); 
    this.capacity = capacity; 
    } 

    protected boolean removeEldestEntry(Entry eldest) { 
    return size() > capacity; 
    } 
} 

這很容易。但是,它只是在地圖上加上一個固定的大小。我運行在一個非常小的堆上,根據緩存對象的大小和我選擇的容量,這可能仍然會耗盡內存。對象是任意的,所以我不能估計它們可能有多大。我不想依靠SoftReferences來修剪緩存,因爲那些被清理的方式是不可靠的;它會從虛擬機變成虛擬機,他們可能會很快得到回收,或者他們可能永遠不會回收,直到他們填滿我的堆。

有沒有什麼辦法讓我監視地圖的大小和限制?

回答

3

如果軟/弱引用是出了問題,然後我看到2(非平凡)選項:

1)使用Java的儀器來檢查的實際大小項目添加到地圖。儀器接口提供了一個對象的"shallow" size,您將需要更多代碼來瀏覽引用(並避免重複計數!)。 Here是一種計算一個對象深度大小的解決方案。

2)使用JMX跟蹤GC之後的堆大小,並在達到某個危險閾值時更改映射行爲。請參閱MemoryMXBean javadoc中的「通知」部分。

0

您可以打包Map實現並在putputAll方法中執行大小。

+1

我很困惑,我將如何評估傳入對象的大小?我問的是實際佔用的堆空間字節數,而不是對象數。 – 2010-07-28 20:41:24

2

地圖本身只包含固定大小的條目,其中包含對地圖中「包含」實際對象的引用。您需要重寫所有映射變異方法(即put(),複製構造函數等)以跟蹤從映射引用的對象的大小(甚至可以確定Java對象佔用多少內存?)。然後考慮添加到緩存中的對象本身可能包含對其他對象和/或集合的引用。你有多深?

看看http://www.javapractices.com/topic/TopicAction.do?Id=83

+0

我想這基本上是我問 - 是否有可能確定任意對象的淺和/或保留大小?我知道,這是一個荒謬的問題。 :-P – 2010-07-28 20:43:02

+0

我添加了一個鏈接到我在Google搜索「java大小的對象」中找到的頁面。該結果頁面上有許多有趣的鏈接。 – 2010-07-28 20:55:14

1

正如其他人所說的,您可以使用代理工具來執行此操作。 SizeOf項目爲這種方法提供了一個方便的工具。這可以與ConcrrentLinkedHashMap的加權值概念一起使用,其中Weigher確定一個值消耗多少個單位的容量。這使得緩存除了傳統的最大條目數限制之外,還可以正確處理集合或內存限制。

如果你希望受到堆的束縛,那麼就有一個早期版本的ConcurrentLinkedHashMap的fork來做這件事。這保留了原版的Apache許可證,因此可以根據您的需求進行調整,因爲它與Voldemort一起打包。

http://sizeof.sourceforge.net/

http://code.google.com/p/concurrentlinkedhashmap/

http://github.com/Omega1/voldemort/blob/master/src/java/voldemort/store/memory/ConcurrentLinkedHashMap.java

相關問題