不可忽視的內存區域-直接內存

一提到JVM運行的的內存劃分,相信大家都會第一反應想到堆內存和棧內存。如果再分清楚一些,就是常說的運行時數據五大部分:方法區,虛擬機棧,本地方法棧,堆,程序計數器。

本文重點聊一聊直接內存(Direct Memory),直接內存並不是運行時數據區的一部分,也不是Java虛擬機規範中定義的內在區域。它通過Unsafe類的allocateMemory()方法申請分配內存,可以通過-XX:MAxDirectMemorySize指定,如果不指定 ,默認與Java堆最大值(-Xmx)一樣。

說直接內存,先提一個東西,那就是NIO,至從JDK1.4中新加入了NIO,引入了一種基於通道(Channel)和緩存區(Buffer)的I/O方式,它可以使用Native函數庫直接分配堆外內存,然後通過一個存儲在Java堆中的DirectByteBuffer對象作爲這塊內在的引用進行操作。這樣能在一些場景中顯著提高性能,因爲避免了在Java堆和Native堆中來回複製數據。

顯然,這塊直接內存的分配不會受到Java堆大小的限制,但是,既然是內存,肯定還是會受到本機總內存(包括RAM以及SWAP區或者分頁文件)大小又及處理器尋址空間限制。服務器管理員在配置虛擬機參數時,會根據實際內存設置-Xmx等參數信息,但經常忽略直接內存,使得各個內存區域總和大於總物理內存,從而導致動態擴展時出現OUtOfMemoryError異常。

部分內存在程序運行中也被頻繁地使用,而且也可能導致OOM。當直接內存發生內存溢出時,Heap Dump文件中不會看見明顯的異常,如果發現OOM後Dump文件很小,而程序中使用了NIO(比如使用了Netty這類框架),那就要考慮這方面的問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章