學習《21天學通Java 6》(一)——Java自動內存管理機制

感謝分享  http://blog.sina.com.cn/s/blog_9cc9465901012xh7.html

Java虛擬機在執行java程序的過程中會把它所管理的內存劃分爲若干個不同的數據區。

它們都有各自的用途,以及創建和銷燬時間,有的區域隨着虛擬機的進程的啓動而存在,有的是依賴用戶線程的啓動和結束而建立和銷燬。

 

根據Java虛擬機規範,內存包括以下幾個運行時數據區域:

程序計數區、Java虛擬機棧、本地方法棧、Java堆、方法區、運行時常量池、直接內存。

 

經常有人把Java內存區粗略的分爲堆內存和棧內存,這裏的堆內存是指Java堆,而棧內存是指Java虛擬機棧

 

1.Java虛擬機棧(Java Virtual Machine Stacks)

 

它是“線程私有”的內存,即前面所述的依賴用戶線程的啓動和結束而建立和銷燬。

它的局部變量表存放了編譯器可知的各種基本數據類型、對象引用(注意不是對象本身,而是對象的引用,根據不同的虛擬機實現,對象引用可能是一個指向對象起始地址的引用指針,也可能指向一個代表對象的句柄)和returnAddress類型(指向了一條字節碼指令的地址)。

 

局部變量表所需的內存空間在編譯期間完成分配,當進入一個方法時,這個方法在幀中需要分配多大的局部變量空間是完全確定的,在方法運行期間不會改變局部變量表的大小。

 

Java虛擬機規範中,這個區域有兩種異常狀況:如果線程請求的棧深度大於虛擬機所允許的深度,將拋出StackOverflowError異常,如果虛擬機棧可以動態擴展,當擴展時無法申請到足夠的內存時會拋出OutOfMemoryError異常。

 

2.Java堆(Java Heap)

 

對大多數應用來說,Java堆是Java虛擬機所管理的內存的最大的一塊。Java堆是被所有線程共享的一塊內存區域,在虛擬機啓動時創建。此內存區域的唯一目的就是存放對象實例,數組和所有的對象實例都在這裏分配內存。(但是由於一些新技術的出現使得這並不是那麼“絕對”了)

 

Java堆可以處於物理上不連續的內存空間中,只要邏輯上是連續的即可。在實現時,可以實現稱固定大小的,也可以是可擴展的,當前主流的虛擬機都是按可擴展的來實現的。如果堆中沒有內存完成實例分配,並且堆也無法再擴展時,將會拋出OutOfMemoryError異常。

 

3.程序計數器(Program Counter Register)

 

它是一塊較小的內存空間,其作用可以看成是當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型中,字節碼解釋器工作時就是通過改變這個計數器的值來選取下一條需要執行的字節碼指令,分支、循環、跳轉、異常處理和線程恢復等基礎功能都需要依賴這個計數器來完成。

 

由於Java的多線程是通過線程輪流切換並分配處理器執行時間的方式來實現的,在任何一個確定的時刻,一個處理器只會執行一條線程中的指令。因此,爲了線程切換後能恢復到正確的執行位置,每條線程都需要有一個獨立的程序計數器,互不影響,獨立存儲,所以它是“線程私有”的內存

 

4.本地方法棧(Native Method Stacks)

與虛擬機棧發揮的作用非常相似,其區別是虛擬機棧

爲虛擬機執行Java方法服務,而本地方法棧則爲虛擬機使用到的Native方法服務。(Sun Hotpot虛擬機直接把本地方法棧和虛擬機方法棧合二爲一)

 

5.方法區(Method Area)

 

與Java堆一樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。Java虛擬機規範把方法區描述爲堆的一個邏輯部分。

 

6.運行時常量池(Runtime Constant Pool)

 

是方法區的一部分,用於存放編譯期間生成的各種字面量和符號引用。

 

7.直接內存

 

直接內存並不是虛擬機運行時數據區的一部分,也不少Java虛擬機規範中定義的內存區域,但是這部分內存也被頻繁地使用,而且也可能導致OutOfMemoryError異常出現。


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