Java虛擬機在執行Java程序的過程當中會把它所管理的內存劃分爲若干個不一樣的數據區域。 以下圖所示:算法
當前線程所執行的字節碼的行號指示器
。字節碼解釋器工做時就是經過改變這個計數器的值來選取下一條須要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復等基礎功能都需 要依賴這個計數器來完成。爲了線程切換後能恢復到正確的執行位置,每條線程都須要有一個獨立的程序計數器,各條線程之間計數器互不影響,獨立存儲,咱們稱這類內存區域爲「線程私有」的內存。
惟一一個在Java虛擬機規範中沒有規定任何OutOfMemoryError狀況的區域
。Java方法執行的內存模型
:每一個方法在執行的同時都會建立一個棧幀(Stack Frame)用於存儲局部變量表、操做數棧、動態連接、方法出口 等信息。每個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機棧中入棧到出棧的過程。局部變量表
存放了編譯期可知的各類基本數據類型(boolean、byte、char、short、int、 float、long、double)、對象引用(reference類型,它不等同於對象自己,多是一個指向對象起始地址的引用指針,也多是指向一個表明對象的句柄或其餘與此對象相關的位置)和returnAddress類型(指向了一條字節碼指令的地址)。編譯期間完成分配
,當進入一個方法時,這個方法須要在幀中分配多大的局部變量空間是徹底肯定的,在方法運行期間不會改變局部變量表的大小。
與虛擬機棧所發揮的做用是很是類似的,它們之間的區別不過是虛擬機棧爲虛擬機執行Java方法(也就是字節碼)服務,而本地方法棧則爲虛 擬機使用到的Native方法服務。服務器
惟一目的就是存放對象實例
,幾乎全部的對象實例都在這裏分配內存。運行時常量池
(Runtime Constant Pool)是方法區的一部分,用於存放編譯期生成的各類字面量和符號引用,這部份內容將在類加載後進入方法區的運行時常量池中存放
。運行時常量池相對於Class文件常量池的另一個重要特徵是具有動態性
,Java語言並不要求常量必定只有編譯期才能產生,也就是並不是預置入Class文件中常量池的內容才能進入方 法區運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用得比較 多的即是String類的intern()方法。並非虛擬機運行時數據區的一部分,也不是Java虛擬機規範中定義的內存區域,可是這部份內存也被頻繁地使用,並且也可能致使OutOfMemoryError異常出現。顯然,本機直接內存的分配不會受到Java堆大小的限制,可是,既然是內存,則確定仍是會受到本機總內存的大小及處理器尋址空間的限制。服務器管理員配置虛擬機參數時,通常會根據實際內存-Xmx等參數信息,但常常會忽略到直接內存,使得各個內存區域的總和大於物理內存限制(包括物理上的和操做系統級的限制),從而致使動態擴展時出現OutOfMemoryError異常。
多線程