Java虛擬機在執行Java程序的過程當中會把它所管理的內存劃分爲若干個不一樣的數據區域。這些區域都有各自的用途,有的區域是線程共享的,有的區域是線程隔離的。以下圖:java
程序計數器(Program Counter Register)是一塊較小的內存空間,它能夠看作是當前線程所執行的字節碼的行號指示器。字節碼解釋器工做時就是經過這個計數器的值來選取下一條須要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都須要依賴這個計數器來完成。緩存
程序計數器是線程私有的內存區域,保證線程切換後能恢復到正確的執行位置。spa
執行Java方法的時候,這個計數器記錄的是正在執行的虛擬機字節碼的指令的地址;執行native方法的時候,計數器的值爲空(null)。線程
Java虛擬機棧(Java Virtual Machine Stacks)描述的是Java方法執行的內存模型:每一個方法在執行的同時都會建立一個棧幀(Stack Frame)用於存儲局部變量表、操做數棧、動態連接、方法出口燈信息。每一個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。3d
Java虛擬機棧也是線程私有的內存區域,生命週期和線程相同。orm
棧幀對象
在活動線程中,只有虛擬機棧頂的棧幀纔是有效的,稱爲當前棧幀(Current Stack Frame),這個棧幀所關聯的方法稱爲當前方法(Current Method)。執行引用所運行的全部字節碼指令都只針對當前棧幀進行操做。棧幀的概念結構以下圖所示:blog
java虛擬機棧能夠拋出以下異常:生命週期
本地方法棧與虛擬機棧的做用是類似的,它們的區別是:進程
與虛擬機棧同樣,本地方法棧也會拋出StackOverflowError和OutOfMemoryError。
棧表明了處理邏輯,而堆表明了數據。
Java堆是Java虛擬機所管理的內存最大的一塊,也是垃圾收集器管理的主要區域。
Java堆是全部線程共享的,堆中的共享常量和緩存能夠被全部棧訪問,節省了空間。
爲了更好的回收內存,或者更好的分配內存,將Java堆細分爲新生代和老年代。
關於每一個區如何回收內存,什麼時候回收內存在下一篇中再總結。
堆的大小也是能夠調整的,能夠經過虛擬機參數-Xmx和-Xms控制。一樣,在該區域,若是沒有內存分配給對象實例,而且堆也沒法再擴展,會拋出OutOfMemoryError異常。
方法區主要用來存儲已經被JVM加載的類信息、常量、靜態變量等。
在過去(當自定義類加載器使用不廣泛的時候),類幾乎是「靜態的」而且不多被卸載和回收,所以類也能夠被當作「永久的」。另外因爲類做爲JVM實現的一部分,它們不禁程序來建立,由於它們也被認爲是「非堆」的內存。
方法區也是全部線程共享的內存區域。
方法區和Java堆同樣,也是須要進行垃圾回收的,該區域的內存回收目標主要是針對常量池的回收的和對類型的卸載。
當方法區沒法知足內存分配需求時,將拋出OutOfMemoryError異常。
永久代是Hotspot中的一個概念,其餘JVM的實現未必有,例如JRockit就沒有(只要不觸碰進程可用內存上限就不會出問題)。Hotspot使用在內存中劃分出一塊區域來存儲類的元信息、類變量以及內部字符串等,稱爲永久代,把它做爲方法區來使用。
永久代是一段連續的內存空間,咱們在JVM啓動以前能夠經過設置-XX:MaxPermSize的值來控制永久代的大小,32位機器默認的永久代的大小爲64M,64位的機器則爲85M。永久代的垃圾回收和老年代的垃圾回收是綁定的,一旦其中一個區域被佔滿,這兩個區都要進行垃圾回收。
Hotspot在Java8中將類的元數據移到了一個與堆不相連的本地內存區域,這個區域就是元空間。
因爲類的元數據分配在本地內存中,元空間的最大可分配內存就是系統可用內存空間。用戶能夠經過-XX:MaxMetaspaceSize爲元空間設置一個空間可用最大值,若是不進行設置,JVM會根據類的元數據大小動態增長元空間的容量。
每個類加載器的存儲區域都稱做一個元空間,全部的元空間合在一塊兒就是咱們一直說的元空間。當一個類加載器被垃圾回收器標記爲再也不存活,其對應的元空間會被回收。在元空間的回收過程當中沒有重定位和壓縮等操做。可是元空間內的元數據會進行掃描來肯定Java引用。
元空間虛擬機負責元空間的分配,其採用的形式爲組塊分配。組塊的大小因類加載器的類型而異。在元空間虛擬機中存在一個全局的空閒組塊列表。當一個類加載器須要組塊時,它就會從這個全局的組塊列表中獲取並維持一個本身的組塊列表。當一個類加載器再也不存活,那麼其持有的組塊將會被釋放,並返回給全局組塊列表。
元空間虛擬機採用了組塊分配的形式,同時區塊的大小由類加載器類型決定。類信息並非固定大小,所以有可能分配的空閒區塊和類須要的區塊大小不一樣,這種狀況下可能致使碎片存在。元空間虛擬機目前並不支持壓縮操做,因此碎片化是目前最大的問題。
參考資料: