標籤:java 記憶體溢出 記憶體管理
**Java記憶體存放地區與記憶體溢出異常(一)**
Java虛擬機器在執行Java程式的過程中會把它所管理的記憶體劃分為若干個不同的資料區域,這些地區都有著各自的用途,以及建立和銷毀的時間,有的地區隨著虛擬機器進程的啟動而存在,有些地區則是依賴於使用者進程的啟動和結束而建立和銷毀,java虛擬機器所管理的記憶體將會包括以下幾個運行時資料區域,一。
1、在這裡先介紹程式計數器
程式計數器(Program Counter Register)是一塊記憶體較小的記憶體空間,它的作用可以看作是當
前線程所執行的字節碼的行號指標,在虛擬機器的概念性模型中,位元組碼解譯器工作時就是通過改變這個
計數器的值來選取下一條需要執行的位元組碼指令,分支、迴圈、跳轉、異常處理、線程恢複等基礎功能
都需要依賴這個計數器來完成。
由於Java虛擬機器的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,
一個處理器只會執行一條線程中的指令,因此,為了切換後能恢複正確的執行位置,每條線程都需要一個獨立的程式計數器,
各條線程之間的計數器互不影響,隔離儲存區 (Isolated Storage),我們稱這類記憶體存放地區為“線程私人的記憶體”。
Java虛擬機器棧
Java虛擬機器(Java Virtual Machine Stacks)與程式計數器相同,也是線程私人的,它的生命週期與線程,
虛擬機器棧描述的是Java方法執行的記憶體模型,每個方法被執行的時候都會同時建立一個棧幀,用於儲存局部變數表、
運算元棧、動態連結、方法出口等資訊。每一個方法被調用直至執行完成的過程,就對應著一個棧幀在虛擬機器從入
棧到出棧的過程。
局部變數表存放了八種基礎資料型別 (Elementary Data Type)(int,double,float,byte,char,short,long,boolean),以及對象引用
(reference類型,它不等同於對象本身,根據不同的虛擬機器實現,它可能是一個指向對象起始地址的引用指標,
也可能指向一個代表對象的控制代碼或者其他與此對象相關的位置)和returnAddress類型(指向一條位元組碼指令的地址).
3、本地方法棧
本地方法棧(Native Method Stacks)與虛擬機器棧所發揮的作用是非常相似的,其區別不過是虛擬機器所執行的
Java方法服務,而本地方法棧則是為虛擬機器使用的Native方法服務,虛擬機器規範中對本地方法棧中的方法使用的
語言、使用方式、與資料結構並沒有強制規定,因此具體的虛擬機器可以自由實現它。
4、Java堆
Java堆(Java Heap)是Java虛擬機器所管理的記憶體中最大的一塊,Java堆是被所有是被所有線程共用的一塊內
存地區,在虛擬機器啟動時建立,此記憶體地區的唯一目的就是存放對象執行個體,幾乎所有的對象執行個體都在這裡分配記憶體,
這一點在Java虛擬機器規範中描述的是:所有的對象執行個體以及數組都要在堆上分配,但是隨著JIT編譯器的發展和逃逸
分析技術逐漸成熟,棧上分配、標量替換最佳化技術都將會導致一些微妙的變化發生,所有的對象都分配在堆上也漸漸
變得不是那麼絕對了。
Java堆是垃圾收集器管理的主要區域,因此很多時候也被稱為GC堆,如果從記憶體回收的角度來看,由於現在的收
集器都是採用分代收集演算法,所以Java堆還可以細分為:新生代和老年代。不過,無論如何劃分,都與存放內容無關,
無論哪個地區,儲存的都是對象執行個體,進一步劃分的目的是為了更好的回收記憶體,或者更快的分配記憶體。
5、方法區
方法區(Method Area)與Java堆一樣,是各個線程共用的記憶體地區,它用於儲存已被虛擬機器載入的類資訊、
常量、靜態變數、及時編譯器後的代碼等資料,雖然Java虛擬機器規範是把方法區描述為堆的一個邏輯部分,
但是它卻有一個別名叫做Non-Heap(非堆),目的可能是與Java堆區分開來。
6、運行時常量池
運行時常量池(Runtime Constant Pool)是方法區的一部分,Class檔案中除了有類的版本、欄位、方法、
介面等描述資訊外,還有一項資訊是常量池(Constant Pool),用於存放編譯期產生的各種字面量和符號引用。
運行時常量池相對於Class檔案常量池的另外一個重要特徵是具備動態性,Java語言並不要求常量一定只
能在編譯期產生,也就是並非預置入Class檔案中常量池的內容才能進入方法區運行時常量池,運行期間也可
能將新的常量放入池中。
Java記憶體存放地區和記憶體溢出異常就先講到這裡,下一節再寫關於記憶體溢出所產生的異常。
Java記憶體存放地區與記憶體溢出異常(一)