重讀《深入理解Java虛擬機》
阿新 • • 發佈:2017-06-02
-xmx 垃圾收集 劃分 tac 棧內存 列表 進行 nbsp 申請
一、Java虛擬機內存區域如何劃分
1、Java虛擬機內存區域的劃分
| 區域名稱 | 作用(用途) | 類型 | 特點 | 虛擬機規定異常情況 | 其他說明 |
1 | 程序計數器 | 指示當前正在執行的字節碼指令地址 | 線程私有 | 1、內存空間較小 2、隨用戶進程的啟動和結束而建立和銷毀。 | 無 | 每個線程都有獨立的程序計數器。執行Native方法時為空指針。 |
2 | 虛擬機棧(棧內存) | Java方法執行的內存模型(方法棧幀入棧、出棧)。每個方法執行的時候都會創建一個棧幀用於存儲局部變量表、操作數,動態鏈接、方法出口等。 為虛擬機執行Java方法服務,用於執行Java方法 | 線程私有 | 1、內存空間較小 2、隨用戶進程的啟動和結束而建立和銷毀 | 1、StackOverflowError:線程請求棧深大於虛擬機所允許的棧深。 2、OutMemoryError:如虛擬機棧可以動態擴展,如果在擴展時無法申請到足夠的內存時拋出異常 | 局部變量表:用於存放編譯期可知的類型,包括基本類型,引用類型,returnAddress類型。局部變量表所需內存空間在編譯期已完成分配,運行期不改變局部變量表大小。 |
3 | 本地方法棧 | 為虛擬機使用到的Native方法服務即用於執行Native方法 | 線程私有 | 1、內存空間較小 2、隨用戶進程的啟動和結束而建立和銷毀 | 1、StackOverflowError: 2、OutMemoryError: | |
4 | 堆(GC堆,堆內存) | 用於存放對象實例,幾乎所有的對象實例都在這裏分配 | 線程共享 | 1、內存空間較大; 2、隨虛擬機進程啟動而創建 3、垃圾收集器主要管理的區域 4、不需要連續的內存空間,只要邏輯上連續即可 | 1、OutMemoryError:堆中沒有內存可用於完成實例分配,並且堆也無法再擴展的時候拋出 | 1、根據垃圾收集器實現算法(分代收集算法)分為:Eden空間、From Survivor空間、ToSurvivor空間。(新生代,老年代) 2、從內存分配角度:堆可劃分為多個線程私有的分配緩存區,目的是為了更好的回收內存和更快的分配內存 |
5 | 方法區(非堆) | 用於存儲虛擬機已經加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼 | 線程共享 | 1、堆內存的一個邏輯部分 2、內存回收主要針對常量池的回收和類型的卸載 | 1、OutMemoryError:方法去無法滿足內存分配需求時拋出,即沒有足夠的內存用於分配 | 運行常量池:用於存放編譯期生成的各種字面量和符號引用,在類加載後進入運行時常量池時存放。運行時常量池具備動態性即常量可以在編譯期內產生也可以在運行期添加新的常量··· |
直接內存不是Java內存區域。
2、堆內存空間內:對象實例的創建、內存布局和內存定位
(1)堆內存空間內對象如何創建分配
1)根據new指令的類型常量在常量池內定位到該類型的符號引用、並判斷該類是否已加載、解析和初始化
2)如果判斷類型信息未加載則進行加載
3)在堆內分配指定大小的堆內存空間
如何分配堆內存空間:a、指針碰撞:即堆內存空間物理上是連續分配的,分配相對規整的,在用過的內存往未用過的內存方向進行分配
b、空閑列表:即堆內存空間不是規整分配的,使用一個空閑列表記錄當前未分配的內存空間,分配時在該空閑列表內查詢符合指定大小的內存空間進行分配
如何保證內存分配的正確性:線程私有分配緩沖區(TLAB),每個線程獨立分配一塊小內存區域(本地線程分配緩沖),每個線程只在自己的TLAB內分配實例對象。設置TLAB:-XX:+/-UseTLAB
4)自動初始化:初始化內存空間的默認值
5)設置對象頭信息
6)執行init初始化方法按照對象聲明位置進行初始化
(2)堆內存空間內對象如何布局
1)對象頭
2)實例數據
3)對齊
(3)堆內存空間內對象如何定位
1)句柄
2)直接指針
3、OOM異常調試和參數設置
溢出區域 | 參數設置 | 異常拋出條件 | 其他說明 |
堆 | -Xms -Xmx | 堆內存無法自動擴展,沒有足夠內存分配實例對象 | 設置參數-XX:+HeapDumpOnOutMemoryError在出現異常時Dump出現當前內存堆轉儲快照用於事後分析 |
虛擬機棧和本地方法 | -Xss:設置虛擬機棧大小 -Xoss:設置本地方法大小 | 1、StackOverflowError:線程請求棧深大於虛擬機所允許的棧深。 2、OutMemoryError:如虛擬機棧可以動態擴展,如果在擴展時無法申請到足夠的內存時拋出異常 | 每個線程分配的虛擬機棧容量越大,則可建立的線程數就越少 |
方法區和運行時常量 | -XX:PermSize方法區最小容量 -XX:MaxPermSize:最大方法區容量 | 1、OutMemoryError:方法去無法滿足內存分配需求時拋出,即沒有足夠的內存用於分配 | |
直接內存 | -XX:MaxDirectMemorySize:指定直接內存最大容量,如果不指定默認與堆同等大小容量 | 1、OutMemoryError:方法去無法滿足內存分配需求時拋出,即沒有足夠的內存用於分配 | 不屬於Java內存區域 直接內存=物理內存-各個區域內存總和 |
二、如何實現垃圾收集和內存分配
三、虛擬機性能如何監控、如何處理故障、如何分析
四、Java程序如何存儲(類文件結構)
五、Java程序如何載入(類的加載機制)
六、Java程序如何執行(虛擬機字節碼執行引擎)
七、Java程序代碼如何優化
八、Java的內存模型
九、Java線程
重讀《深入理解Java虛擬機》