JVM的Heap Memory和Native Memory

JVM管理的內存可以總體劃分爲兩部分:Heap Memory和Native Memory。前者我們比較熟悉,是供Java應用程序使用的;後者也稱爲C-Heap,是供JVM自身進程使用的。Heap Memory及其內部各組成的大小可以通過JVM的一系列命令行參數來控制,在此不贅述。Native Memory沒有相應的參數來控制大小,其大小依賴於操作系統進程的最大值(對於32位系統就是3~4G,各種系統的實現並不一樣),以及生成的Java字節碼大小、創建的線程數量、維持java對象的狀態信息大小(用於GC)以及一些第三方的包,比如JDBC驅動使用的native內存。

Native Memory裏存些什麼?

  1. 管理java heap的狀態數據(用於GC);
  2. JNI調用,也就是Native Stack;
  3. JIT(即使編譯器)編譯時使用Native Memory,並且JIT的輸入(Java字節碼)和輸出(可執行代碼)也都是保存在Native Memory;
  4. NIO direct buffer。對於IBM JVM和Hotspot,都可以通過-XX:MaxDirectMemorySize來設置nio直接緩衝區的最大值。默認是64M。超過這個時,會按照32M自動增大。
  5. 對於IBM的JVM某些版本實現,類加載器和類信息都是保存在Native Memory中的。

DirectBuffer的好處

DirectBuffer訪問更快,避免了從HeapBuffer還需要從java堆拷貝到本地堆,操作系統直接訪問的是DirectBuffer。DirectBuffer對象的數據實際是保存在native heap中,但是引用保存在HeapBuffer中。 
另外,DirectBuffer的引用是直接分配在堆得Old區的,因此其回收時機是在FullGC時。因此,需要避免頻繁的分配DirectBuffer,這樣很容易導致Native Memory溢出。

爲什麼會內存溢出?

簡單理解java process memory = java heap + native memory。因此內存溢出時,首先要區分是堆內存溢出還是本地內存溢出。Native Memory本質上就是因爲耗盡了進程地址空間。對於HotSpot JVM來書,不斷的分配直接內存,會導致如下錯誤信息:Allocated 1953546760 bytes of native memory before running out

參考資料:

http://www.ibm.com/developerworks/library/j-nativememory-linux/index.html 
http://www.techpaste.com/2012/07/steps-debugdiagnose-memory-memory-leaks-jvm/ 
https://sourcevirtues.wordpress.com/2013/01/14/java-heap-space-and-native-heap-problems/ 
http://www.theotherian.com/2013/08/understanding-javas-native-heap-or-c-heap.html 
http://www.ibm.com/developerworks/library/l-kernel-memory-access/ 
http://www.ibm.com/developerworks/library/j-zerocopy/ 

http://en.wikipedia.org/wiki/Direct_memory_access

原文來源:http://blog.csdn.net/u013721793/article/details/51204001

發佈了26 篇原創文章 · 獲贊 27 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章