1. 程式人生 > >JVM的Heap Memory和Native Memory

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

參考資料: