JVM內存模型-轉載

http://my.oschina.net/u/567296/blog/303780 java

JVM的內部結構以下圖:程序員





JVM主要包括兩個子系統和兩個組件:編程

 

 

1. 兩個子系統分別是Class loader子系統和Execution engine(執行引擎) 子系統;服務器

 

1.1 Class loader子系統的做用:根據給定的全限定名類名(如 java.lang.Object)來裝載class文件的內容到 Runtime data area中的method area(方法區域)。Java程序員能夠extends java.lang.ClassLoader類來寫本身的Class loader。編程語言

 

1.2 Execution engine子系統的做用:執行classes中的指令。任何JVM specification實現(JDK)的核心都是Execution engine,不一樣的JDK例如Sun 的JDK 和IBM的JDK好壞主要就取決於他們各自實現的Execution engine的好壞。spa

 

2. 兩個組件分別是Runtime data area (運行時數據區域)組件和Native interface(本地接口)組件。操作系統

 

2.1 Native interface組件:與native libraries交互,是其它編程語言交互的接口。當調用native方法的時候,就進入了一個全新的而且再也不受虛擬機限制的世界,因此也很容易出現JVM沒法控制的native heap OutOfMemory。.net

 

2.2 Runtime Data Area組件:這就是咱們常說的JVM的內存了。它主要分爲五個部分——線程

一、Heap (堆):一個Java虛擬實例中只存在一個堆空間,Java堆是被全部線程共享的,在虛擬機啓動時建立。Java堆的惟一目的就是存放對象實例,絕大部分的對象實例都在這裏分配。Java堆內還有更細緻的劃分:新生代、老年代,再細緻一點的:edenfrom survivorto survivor,甚至更細粒度的本地線程分配緩衝(TLAB)等,不管對Java堆如何劃分,目的都是爲了更好的回收內存,或者更快的分配內存指針

Java堆能夠處於物理上不連續的內存空間,它邏輯上是連續的便可,就像咱們的磁盤空間同樣。實現時能夠選擇實現成固定大小的,也能夠是可擴展的,不過當前全部商業的虛擬機都是按照可擴展來實現的(經過-Xmx-Xms控制)。若是在堆中沒法分配內存,而且堆也沒法再擴展時,將會拋出OutOfMemoryError異常。

 

二、Method Area(方法區域):被裝載的class的信息存儲在Method area的內存中。當虛擬機裝載某個類型時,它使用類裝載器定位相應的class文件,而後讀入這個class文件內容並把它傳輸到虛擬機中。方法區可能認識它的人還不太多,若是叫永久代(Permanent Generation)它的粉絲也許就多了。它還有個別名叫 作Non-Heap(非堆)

方法區中存放了每一個Class的結構信息,包括常量池、字段描述、方法描述等等。Class文件中除了有類的版本、字段、方法、接口等描述等信息外,還有一項信息是常量表(constant_pool table),用於存放編譯期已可知的常量,這部份內容將在類加載後進入方法區(永久代)存放。可是Java語言並不要求常量必定只有編譯期預置入Class的常量表的內容才能進入方法區常量池,運行期間也可將新內容放入常量池(最典型的String.intern()方法)。

運行時常量池是方法區的一部分,天然受到方法區內存的限制,當常量池沒法在申請到內存時會拋出OutOfMemoryError異常。

 

三、Java Stack(java的棧):虛擬機只會直接對Java stack執行兩種操做:以幀爲單位的壓棧或出棧。棧描述的是Java方法調用的內存模型:每一個方法被執行的時候,都會同時建立一個幀(Frame)用於存儲本地變量表、操做棧、動態連接、方法出入口等信息。每個方法的調用至完成,就意味着一個幀在VM棧中的入棧至出棧的過程


四、Program Counter(程序計數器):每個線程都有它本身的PC寄存器,也是該線程啓動時建立的。PC寄存器的內容老是指向下一條將被執行指令的餓地址,這裏的地址能夠是一個本地指針,也能夠是在方法區中相對應於該方法起始指令的偏移量。

  
五、Native method stack(本地方法棧):保存native方法進入區域的地址.
以上五部分只有Heap 和Method Area是被全部線程的共享使用的;而Java stack, Program counter 和Native method stack是以線程爲粒度的,每一個線程獨自擁有本身的部分。

 

此外還有本機直接內存的管理(Direct Memory) -- 直接內存並非虛擬機運行時數據區的一部分,它根本就是本機內存而不是VM直接管理的區域。

顯然本機直接內存的分配不會受到Java堆大小的限制,可是即然是內存那確定仍是要受到本機物理內存(包括SWAP區或者Windows虛擬內存)的限制的,通常服務器管理員配置JVM參數時,會根據實際內存設置-Xmx等參數信息,但常常忽略掉直接內存,使得各個內存區域總和大於物理內存限制(包括物理的和操做系統級的限制),而致使動態擴展時出現OutOfMemoryError異常。

 

JVM內存模型實例以及參數對應:

相關文章
相關標籤/搜索