2.1概述
講解內(nèi)存各個(gè)區(qū)域的作用、服務(wù)對象以及其中可能產(chǎn)生的問題
2.2運(yùn)行時(shí)數(shù)據(jù)區(qū)
2.2.1程序計(jì)數(shù)器
當(dāng)前線程所執(zhí)行的字節(jié)碼的行號顯示器
每個(gè)線程都有獨(dú)立的程序計(jì)數(shù)器椒楣,既線程私有
線程執(zhí)行Java方法赴蝇,計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址
線程執(zhí)行Native方法,計(jì)數(shù)器值為空
唯一一個(gè)在Java虛擬機(jī)規(guī)范中沒有OutOfMemoryError情況的區(qū)域
2.2.2Java棧
線程私有迎罗,生命周期和線程相同
Java方法執(zhí)行的內(nèi)存模型睬愤,每個(gè)方法在執(zhí)行的同時(shí)會創(chuàng)建一個(gè)棧幀,用于存儲局部變量表纹安,操作數(shù)棧尤辱,動態(tài)鏈接,方法出口等信息厢岂,方法調(diào)用到完成的過程光督,對應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中的入棧到出棧的過程
局部變量表
編譯期可知的各種數(shù)據(jù)類型
對象引用
returnAddress類型:指向一條字節(jié)碼指令的地址
64位長度的long和double占兩個(gè)局部變量空間
內(nèi)存空間在編譯器分配完成
兩種異常:StackOverflowError:線程請求的棧深度大于虛擬機(jī)所允許的深度;OutOfMemoryError:動態(tài)擴(kuò)展時(shí)無法申請到足夠的內(nèi)存
2.2.3本地方法棧
使用native方法服務(wù)
也會拋出StackOverflowError和OutOfMemoryError
2.2.4 Java堆
被所有線程共享塔粒,虛擬機(jī)啟動的時(shí)候創(chuàng)建
唯一目的是存放對象實(shí)例
垃圾收集器管理的主要區(qū)域
劃分:更好的回收內(nèi)存或分配內(nèi)存【新生代(Eden结借、From Survivor、To Survivor)】【老年代】
可物理上不連續(xù)卒茬,邏輯上連續(xù)
2.2.5方法區(qū)
各個(gè)內(nèi)存共享
存放被虛擬機(jī)加載的類信息船老、常量、靜態(tài)變量圃酵、即時(shí)編譯器編譯的代碼等
2.2.6運(yùn)行時(shí)常量池
方法區(qū)的一部分
Class文件中的常量池柳畔,用于存放編譯期生成的各種字面量和符號引用,類加載后進(jìn)入常量池存放
運(yùn)行期間也可以將新的常量放入常量池 String 的 intern()方法
2.2.7直接內(nèi)存
使用Native函數(shù)庫直接分配堆外內(nèi)存郭赐,通過一個(gè)存儲在JAVA堆中的DirectByteBuffer對象作為這塊內(nèi)存區(qū)域的引用直接操作
2.3HotSpot虛擬機(jī)對象探秘
堆中對象的創(chuàng)建薪韩、布局和訪問的全過程
2.3.1對象的創(chuàng)建
虛擬機(jī)遇到New指令
首先檢查指令的參數(shù)能否在常量池中定位到一個(gè)類的符號引用
檢查這個(gè)符號引用對應(yīng)的類是否已被加載、解析堪置、初始化過
沒有加載躬存,則需要先加載
為新生對象分配內(nèi)存區(qū)域(指針碰撞&空閑列表)
線程安全(方案1:對分配內(nèi)存空間的動作同步;方案2:本地線程分配緩沖 TLAB)
對對象進(jìn)行必要的設(shè)置
調(diào)用init方法
2.3.2對象的內(nèi)存布局
對象頭(存放對象自身的運(yùn)行時(shí)數(shù)據(jù)&類型指針)
實(shí)例數(shù)據(jù)
對齊填充
2.3.3對象的訪問定位
句柄訪問
直接指針
2.4實(shí)戰(zhàn):OutOfMemoryError異常
2.4.1 JAVA堆溢出
將堆的最小值-Xms和最大值-Xmx設(shè)置相同可避免堆自動擴(kuò)展
出現(xiàn)內(nèi)存溢出時(shí)內(nèi)存堆轉(zhuǎn)儲快照打右ㄏ恰:設(shè)置-XX:HeapDumpOnOutOfMemory
分析快照岭洲,對象是否必要?
內(nèi)存溢出:指程序在申請內(nèi)存時(shí)坎匿,沒有足夠的內(nèi)存空間供其使用盾剩。檢查堆大小替蔬;檢查對象生命周期告私、對象狀態(tài)過長的情況
內(nèi)存泄露:指程序在申請內(nèi)存后,無法釋放已申請的內(nèi)存空間承桥。分析泄露對象到GC Root的引用鏈
2.4.2虛擬機(jī)棧和本地方法棧溢出
棧容量由-Xss設(shè)定
減少線程數(shù)
更換64位虛擬機(jī)
減少最大堆和減少棧容量來換取更多的線程
2.4.3方法區(qū)和運(yùn)行時(shí)常量池溢出
2.4.4本機(jī)直接內(nèi)存溢出
參考文獻(xiàn):
[1] 深入理解Java虛擬機(jī) 第二版 --周志明