2011-12-08 15 views
3

我想緩存在我記憶中的應用產生的數據寫入高速緩存,但是如果內存變得稀缺,我想將數據交換到磁盤。如何實現數據交換到磁盤,只有當可用內存低

理想我希望通過VM通知,它需要的內存和我的數據寫入磁盤並釋放一些內存的方式。但我沒有看到任何方式對自己掛接到虛擬機中,通知我的方式之前發生的OutOfMemoryError某處(最有可能以任何方式不相關的緩存代碼)。

java.lang.ref中的引用類在這種情況下似乎沒有任何用處,它們的通知機制(ReferenceQueue)僅在引用已被GC回收後觸發。那麼將數據保存到磁盤就太晚了。

有什麼替代方法可以有效地管理堆內存? (不交換到磁盤,直到絕對不可避免的)


EDIT1:針對註釋「操作系統已經這樣做,對你」 - 這僅覆蓋了問題的一部分 - 的內存OS量可以分配是有限的資源。也有這裏需要考慮的其他限制比可用內存量的OS:

  • 通過虛擬機的架構所施加的限制(32-Bit VM
  • 可以分配到的內存限制虛擬機的過程(32-Bit OS
  • 的限制可能使用-Xmx選項

只需無限堆大小運行虛擬機不會阻止其運行內存,即使實行虛擬機上的操作系統仍然有充足的可用性,由於以上原因,VM可能無法使用。

+2

大多數操作系統都爲您處理。你爲什麼希望重新實現它? –

+0

並強化上述評論:http://en.wikipedia.org/wiki/Paging – jweyrich

+0

@George通常,您不會選擇進入磁盤或不進行任何操作。你可能有一些你不想經常訪問的任務關鍵數據,你不想從虛擬內存中加載,但是操作系統決定把它放在那裏。 – corsiKa

回答

0

您可以編寫一個線程來重複檢查空閒內存,並在傳遞限制時採取行動。

1

我建議您使用一些API調用來監視可用的可用內存並相應地執行操作。

this question有關如何監視的可用內存給JVM量。

+0

我希望有更好的方法。監視空閒內存意味着高速緩存始終需要保持儘可能多的內存空間,因爲應用程序可以在最差的情況下在兩次檢查之間進行分配。 – Durandal

0

我會用一個內部數據庫(德比想到爲發展宗旨,以部署您選擇的味道替換它)。通常他們已經內置了這個功能,你可以配置多少數據庫保存在內存中。

+0

據我所知,數據庫(和Derby也不例外)在事務成功之前總是將所有內容提交給磁盤。這就是磁盤上存在的數據,一部分緩存在內存中。這是微妙的,但在我的情況下決定性的差異,如果內存足夠,我不想將數據寫入磁盤。 – Durandal

0

這是一個非常困難的事情在純Java做的,因爲你已經在暗示的原因。

  • 這是很正常的堆變得幾乎全部GC踢之前,所以唯一的辦法,你可以決定多少空閒的內存真的可以是做一個GC(和你不想要經常這樣做)。您可以使用CMSInitiatingOccupancyFraction選項來確保GC在發生80%裝滿時發生 - 然後您可以假設Management API返回的「空閒內存」的值可能是正確的(對於值> 80%) 。但是,當然沒有保證。

  • 至於你提到的軟引用會自動收集器被添加到與它們註冊的隊列前清零,所以它們不是特別有幫助這裏。你可能會創建一個虛擬軟引用,並使用它作爲表示內存不足的指示。但是我不確定時機 - 你能保證在JVM耗盡內存之前將所有數據轉儲到磁盤嗎?可能不會。

你能代替刷新緩存到磁盤當它達到一定的規模,例如如果它超過500MB,然後沖洗它?

或者你可以使用MappedByteBuffer與私有映射 - 數據不會被刷新到磁盤?如果我沒有記錯的話,你寫的數據存儲在堆外的「直接」內存中(至少在Linux上),所以不會消耗你的任何堆 - 但請檢查。如果RAM耗盡,你當然會開始使用Swap。

+0

在設置的內存使用情況下刷新到磁盤不會造成問題,如果沒有更好的選項啓用(最大內存百分比或僅限於設置的最大內存MB),那將是我的備用計劃。你對MappedByteBuffers的建議看起來很有希望,太糟糕了,JRE源不是太有用,它本身沒有顯示多少肉。我會定義檢查出來。 – Durandal

相關問題