jvm虛擬機器學習之記憶體區域介紹

lkj41110發表於2017-01-09
1.java記憶體區域
1.1 概述
java程式設計師把記憶體控制的權力交給了java虛擬機器,不用自己去分配空間,所以不容易出現記憶體洩漏和記憶體溢位。不過,一旦出現記憶體洩漏和溢位的問題,如果不瞭解虛擬機器怎樣使用記憶體,就很難排查錯誤。
1.2執行時資料區域
java虛擬機器會把它所管理的記憶體劃分為幾個不同的區域,每個區域都有自各自的用途。

方法區和堆是執行緒共享的,程式計數器,虛擬機器棧和本地方法棧是獨立的執行緒。

1.2.1 執行緒計數器:是一塊較小的記憶體空間,它可以看作當前執行緒所執行的位元組碼的行號指示器。分支,迴圈,跳轉,異常處理基礎等功能都需要依賴這個計數器。
java虛擬機器的多執行緒是通過執行緒輪流切換並分配處理器執行時間的方式來實現的。為了執行緒切換後能恢復到正確的執行位置,每個執行緒都有個執行緒暫存器,用來儲存已經執行到的位元組碼指令。當然,計數器記錄的是虛擬機器位元組碼指令的地址。

1.2.2java虛擬機器棧:執行方法的同時用虛擬機器棧儲存 區域性變數表,運算元棧,動態連結,方法出口。
我們常常說的java記憶體中的棧和堆是一個大致的說法,實際上虛擬機器記憶體劃分複雜的多。我們所說的棧主要指java虛擬機器棧或者說java虛擬機器棧中的區域性變數表,主要存放了8種基本型別,物件的引用(這個大家應該很熟悉)和returnAddress型別(指向一條位元組碼指令的地址)。

1.2.3 本地方法棧:和java虛擬機器棧相似,虛擬機器棧為java方法(也就是位元組碼)服務,但是本地方法棧為native方法服務。有些虛擬機器把這兩個棧合併了。

1.2.4 java堆:java堆是虛擬機器管理的記憶體最大的一塊,存放了幾乎所有的物件例項,是被所有的執行緒共享的一塊記憶體區域。所以,java堆是垃圾蒐集器管理的主要區域。

1.2.5 方法區:用於存放虛擬機器載入的類資訊,常量,靜態常量,即時編譯器編譯的程式碼資料,也叫“非堆”,目的是與java堆區分開來。
java虛擬機器規範對方法區的限制非常寬鬆,除了和java堆一樣不需要連續的記憶體和可以選擇固定大小或者可擴充套件外,還可以選擇不實現垃圾收集。相對而言,垃圾收集這個行為在這個區域是比較少出現的,回收的效果也比較難以令人滿意,但是這部分割槽域的回收的確也是必要的。

1.2.6 執行時常量池:執行時常量是方法區的一部分。Class檔案的常量池,用於存放編譯期生成的字面量和符號引用,當這部分內容將在類載入後進入方法區的執行時常量池。

1.2.7 直接記憶體:直接記憶體(Direct Memory)並不是虛擬機器執行時資料區的一部分,也不是Java虛擬機器規範中定義的記憶體區域,但是這部分記憶體也被頻繁地使用,而且也可能導致OutOfMemoryError異常出現。
JDK1.4加的NIO中,ByteBuffer有個方法是allocateDirect(int capacity) ,這是一種基於通道(Channel)與緩衝區(Buffer)的I/O方式,它可以使用Native函式庫直接分配堆外記憶體,然後通過一個儲存在Java堆裡面的DirectByteBuffer物件作為這塊記憶體的引用進行操作。這樣能在一些場景中顯著提高效能,因為避免了在Java堆和Native堆中來回複製資料。

以上資料均出於:《深入理解Java虛擬機器》

相關文章