java內存區域

運行時數據區域  java

  java虛擬機在執行java程序的過程當中會把它管理的內存分爲不一樣的數據區域,不一樣的數據區域功能不一樣,以及它的建立和銷燬時間不一樣,有的區域隨着虛擬機的啓動而存在,有的區域依賴用戶線程的啓動和結束而創建和銷燬。數組

 

程序計數器:是一塊小的內存,能夠認爲是當前線程所執行的字節碼的行號指示器。(執行到底哪裏了),多線程之間輪流切換分配處理器的執行時間,在任什麼時候刻一個處理執行一個線程中的指令,線程切換後爲了能及時恢復到正確的位置,每一個線程內都須要一個程序計數器,各個線程之間的計數器互不干擾,是線程的私有內存。
若是程序執行的是java方法,計數器記錄的是正在執行的字節碼的指令地址,若是執行的是本地方法native method,技術器則爲空(undefined)
技術器是惟一一塊在java虛擬機規範中沒有任何規定OutOfMemoryError狀況的區域
 

 Java虛擬機棧:Java虛擬機棧描述的是java方法執行的模型,這部分區域也是線程私有的,生命週期和線程相同。每一個java方法執行的時候都會建立一個棧幀(stack frame),這個棧幀用於存儲局部變量表,操做站、動態連接、方法出口等信息。每一個方法的調用到執行完畢都是對應着一個棧幀在java虛擬棧從入棧到出棧的過程。多線程

 

局部變量表:~存放了在編譯期可知的各類基本數據類型,對象引用類型 (不是對象自己)和 returnAddress類型(執行一條字節碼指令的地址)。其中64位的長度的long和double類型的數據會佔用2個局部變量空間(slot),其他的數據類型都只佔用1個,局部變量表所須要的內存空間在編譯期間就已經分配完成。當java方法調用執行的時候,這個方法在棧幀中分配多大的內存已經徹底肯定了,運行期間是不會改變局部變量表的大小。
在java虛擬機規範中,對此區域規定了兩種異常:(1)當線程請求的棧深度大於虛擬機所容許的深度,則會拋出StackOverflowError (2)若是虛擬機動態擴展,當擴展到沒法申請到足夠的內存空間的時候(系統內存有限),會拋出OutOfMemeryError
 
本地方法棧:Native Method Stack 和 java虛擬機棧發揮的做用是同樣,只不過java虛擬機棧是執行java方法,而本地方法棧是執行native方法。一樣的道理,本地方法也會拋出StackOverflowError和OutOfMemeryError
 
 
Java堆:java heap 是虛擬機中管理的內存中最大的一塊,是全部線程共享的一塊內存區域。java heap的惟一目的就是存放對象實例,幾乎全部的對象實例都在這裏分配內存。java虛擬機規範描述的是全部的對象實例和數組都要在堆上分配。
java堆是垃圾收集器管理的主要區域,所以也稱爲"GC堆".
Java堆能夠處於物理上不連續的內存空間中,只須要邏輯連續便可。能夠實現成固定大小,也能夠實現爲可擴展(主流虛擬機都設計成可擴展,經過-Xmx 和 -Xms控制),當java heap沒有內存完成實例分配,堆也沒法再擴展,將會拋出 OutOfMemeryError
 
 
方法區:Method Area 和 java堆同樣,是全部線程共享的內存區域。用於存儲虛擬機加載的類信息,靜態變量,常量,即時編譯器編譯後的代碼數據等。
運行時常量池:運行時常量池是方法區的一部分,class文件除了有類的版本,方法、接口、字段等的描述信息,還有一項信息就是常量池,用於存放編譯時生成的各類字面量和符號引用,而這部分信息在類加載後存放在方法區中的運行時常量池中。運行時常量池受到方法區內存的限制,運行時常量池沒法申請到內存時也會拋出OutOfMemeryError異常。
運行時常量池相對於class文件常量池的一個特色是具備動態性,也就是說並不是只在編譯期間,class文件的常量池的內容才能進入運行時常量池,在運行期間,也有可能將常量放入運行時常量池中,例如:String類的intern()方法
 
 
直接內存:直接內存不是運行時數據區的一部分,不是java虛擬機規範定義的內存區域。在NIO類中,使用native方法直接在堆外分配內存,而後經過在java堆中DirectByteBuffer對象對象做爲這塊內存的引用進行操做。避免了java堆和native堆之間的數據來回複製,提升了性能。本機的直接內存不會受到java堆大小的限制,可是仍是會受本機內存大小的限制。當配置各個內存區域大小的時候,忽略了直接內存,使得各個區域內存大小之和大於物理內存限制,則會拋出OutOfMemeryError異常。
相關文章
相關標籤/搜索