深入理解java虛擬機(jī) 摘要
目錄:
一、自動(dòng)內(nèi)存管理機(jī)制
- 運(yùn)行時(shí)數(shù)據(jù)區(qū)域
- HotSpot虛擬機(jī)對(duì)象探秘
- 實(shí)戰(zhàn):OutOfMemoryError異常
- 垃圾收集器與內(nèi)存分配策略
一、自動(dòng)內(nèi)存管理機(jī)制
2. HotSpot虛擬機(jī)對(duì)象探秘
-
對(duì)象的創(chuàng)建:
虛擬機(jī)遇到一條new指令時(shí)俭识,首先將去檢查這個(gè)指令的參數(shù)是否能在常量池個(gè)類的符號(hào)引用,并且檢查這個(gè)符號(hào)引用代表的類是否已被加載友驮、解析和初始化過。如果沒有喇伯,那必須先執(zhí)行相應(yīng)的類加載過程.
在類加載檢查通過后喊儡,接下來虛擬機(jī)將為新生對(duì)象分配內(nèi)存。
內(nèi)存分配完成后稻据,虛擬機(jī)需要將分配到的內(nèi)存空間都初始化為零值(不包括對(duì)象頭),這一步操作保證了對(duì)象的實(shí)例字段在Java代碼中可以不賦初始值就直接使用艾猜,程序能訪問到這些字段的數(shù)據(jù)類型所對(duì)應(yīng)的零值买喧。
接下來,虛擬機(jī)要對(duì)對(duì)象進(jìn)行必要的設(shè)置匆赃,例如這個(gè)對(duì)象是哪個(gè)類的實(shí)例淤毛、如何才能找到類的元數(shù)據(jù)信息、對(duì)象的哈希碼算柳、對(duì)象的GC分代年齡等信息低淡。這些信息存放在對(duì)象的對(duì)象頭(Object Header)之中。根據(jù)虛擬機(jī)當(dāng)前的運(yùn)行狀態(tài)的不同瞬项,如是否啟用偏向鎖等蔗蹋,對(duì)象頭會(huì)有不同的設(shè)置方式。
在上面工作都完成之后囱淋,從虛擬機(jī)的視角來看猪杭,一個(gè)新的對(duì)象已經(jīng)產(chǎn)生了,但從Java程序的視角來看妥衣,對(duì)象創(chuàng)建才剛剛開始——<init>方法還沒有執(zhí)行皂吮,所有的字段都還為零。所以税手,一般來說(由字節(jié)碼中是否跟invokespecial指令所決定)蜂筹,執(zhí)行new指令之后會(huì)接著執(zhí)行<init>方法,把對(duì)象按照程序員的意愿進(jìn)行初始化芦倒,這樣一個(gè)真正可用的對(duì)象才算完全產(chǎn)生出來艺挪。 -
對(duì)象的內(nèi)存布局
對(duì)象頭(Header):包括兩部分信息,第一部分用于存儲(chǔ)對(duì)象自身的運(yùn)行時(shí)數(shù)據(jù)兵扬,如哈希碼(HashCode)闺属、GC分代年齡、鎖狀態(tài)標(biāo)志周霉、線程持有的鎖、偏向線程ID亚皂、偏向時(shí)間戳等俱箱。另外一部分是類型指針,即對(duì)象指向它的類元數(shù)據(jù)的指針灭必,虛擬機(jī)通過這個(gè)指針來確定這個(gè)對(duì)象是哪個(gè)類的實(shí)例狞谱。如果對(duì)象是一個(gè)Java數(shù)組,那在對(duì)象頭中還必須有一塊用于記錄數(shù)組長(zhǎng)度的數(shù)據(jù)禁漓。
實(shí)例數(shù)據(jù)(Instance Data):對(duì)象真正存儲(chǔ)的有效信息跟衅,也是在程序代碼中所定義的各種類型的字段內(nèi)容。無論是從父類繼承下來的播歼,還是在子類中定義的伶跷,都需要記錄起來。這部分的存儲(chǔ)順序會(huì)受到虛擬機(jī)分配策略參數(shù)(FieldsAllocationStyle)和字段在Java源碼中定義順序的影響。
對(duì)齊填充(Padding):沒有特別的含義叭莫,它僅僅起著占位符的作用蹈集。由于HotSpot VM的自動(dòng)內(nèi)存管理系統(tǒng)要求對(duì)象起始地址必須是8字節(jié)的整數(shù)倍,換句話說雇初,就是對(duì)象的大小必須是8字節(jié)的整數(shù)倍拢肆。而對(duì)象頭部分正好是8字節(jié)的倍數(shù)(1倍或者2倍),因此靖诗,當(dāng)對(duì)象實(shí)例數(shù)據(jù)部分沒有對(duì)齊時(shí)郭怪,就需要通過對(duì)齊填充來補(bǔ)全。 -
對(duì)象的訪問定位
建立對(duì)象是為了使用對(duì)象刊橘,我們的Java程序需要通過棧上的reference數(shù)據(jù)來操作堆上的具體對(duì)象鄙才。由于reference類型在Java虛擬機(jī)規(guī)范中只規(guī)定了一個(gè)指向?qū)ο蟮囊茫]有定義這個(gè)引用應(yīng)該通過何種方式去定位伤为、訪問堆中的對(duì)象的具體位置咒循,所以對(duì)象訪問方式也是取決于虛擬機(jī)實(shí)現(xiàn)而定的。目前主流的訪問方式有使用句柄和直接指針兩種绞愚。