總結自《深刻理解java虛擬機》java
不少博客在講虛擬機內存模型時,比較寬泛或者粗化,甚者,不許確,如下是個人一個筆記照片數組
運行時數據區能夠分爲兩部分:線程共享區和線程私有區jvm
1、線程共享區工具
這部分區域又分爲堆(Heap)和方法區(也就是一般所說的非堆內存)開發工具
一、Heapspa
(1)堆是在JVM啓動時建立,主要存放對象實例,在虛擬機規範中的描述是:全部的對象實例以及數組都要在堆上分配,可是隨着技術的發展,這一點也並不絕對了;操作系統
(2)堆是垃圾收集器管理的主要區域,所以有時也成爲"GC堆"(垃圾堆);關於垃圾回收的介紹將在下篇文章單獨介紹線程
(3)當前主流的虛擬機都是按照可擴展的配置來實現堆的分配,也就是咱們在開發工具中常見的配置最大最小堆參數:-Xmx,-Xms對象
(4)若是堆中沒有內存來完成實例分配,也沒法再擴展時,將拋出OutOfMemoryErrorblog
(5)根據java虛擬機的規範,堆能夠處於物理上不連續的內存空間中,只要邏輯上是連續的便可,筆者查閱相關資料理解這句話,這和操做系統的內存管理機制有關,垃圾回收會產生許多小的碎塊,
叫作堆碎片,當某個碎片沒法知足一個較大的對象分配所需的內存時,操做系統能夠將若干不連續的碎片分配給該對象存儲,並登記好碎片區域與該對象信息的一種映射關係來完成;
二、Non-Heap
也就是平時所說的非堆。有的開發者也稱永久代,筆者認爲爲避免歧義,最好忘掉這個稱呼,可自行查閱相關概念
(1)非堆區域主要用於存儲已被虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯後的代碼等。
(2)垃圾收集行爲在該區域較少出現,設置能夠選擇不實現垃圾收集
(3)該區域的內存回收目標主要是針對常量池的回收和對類型的卸載
(4)當方法區沒法知足內存分配需求時將拋出OutOfMemoryError異常
特別的:運行時常量池
Class文件的描述信息中除了類的版本,字段,方法,接口外,還有一項是常量池,用於存放編譯期生成的各類字面量和符號引用,這部分將在類加載完成後進入方法區的運行時常量池中存放
此外,除編譯期的常量外,運行期間產生的新的常量,例如String類的intern()方法產生的String類的常量也會放入運行時常量池中
2、線程私有區
一、VM Stack(java虛擬機棧)
(1)虛擬機棧的生命週期與線程相同
(2)描述的是Java方法執行的內存模型。每一個方法在執行的時候會建立一個棧幀(Stack Frame),用於存儲局部變量表,操做數棧,動態連接,方法出口等信息。每個方法從調用到執行完畢
的過程就對應一個棧幀在虛擬機棧中入棧到出棧的過程
(3)棧溢出:StackOverflowError,寫過遞歸方法的必定對這個異常很敏感,若是線程請求的棧深度大於虛擬機所容許的棧深度,將拋出此異常;內存不夠分配時也可能拋出OutOfMemoryError異常
二、Native Method Stack(本地方法棧)
(1)虛擬機棧爲虛擬機執行java方法服務,而本地方法棧則爲虛擬機使用到的Native方法服務(Native方法不禁java實現,用C、C++實現)
(2)有的虛擬機直接將本地方法棧和虛擬機棧合二爲一,譬如咱們用的最多的HotSpot虛擬機
三、Program Counter Register(程序計數器)
該區域較小,能夠看作是當前線程所執行的字節碼的行號指示器,字節碼解釋器工做時就是經過改變這個計數器的值來選取下一條須要執行的字節碼指令。分支,循環,跳轉,異常處理等基礎功能
都由該計數器來完成。此區域是惟一一個在jvm規範中沒有規定任何OutOfMemoryError狀況的區域
關於該篇提到的垃圾收集,Class文件結構和類加載的內容將在後序的篇章中一一介紹