對象訪問是Java語言中最普通的程序行為赌莺,但即使是最簡單的訪問冰抢,也會涉及虛擬機棧、Java堆和方法區(qū)這三個最重要的內(nèi)存區(qū)域之間的關(guān)聯(lián)關(guān)系艘狭。
最簡單的對象訪問
代碼
Object obj = new Object();
內(nèi)存分配
假設(shè)這句代碼出現(xiàn)在方法體中挎扰,具體的內(nèi)存分配如下:
- “Object obj”這部分語義將會反映到虛擬機棧的本地變量表喘蟆,作為一個reference類型數(shù)據(jù)出現(xiàn)。
- “new Object()”這部分語義將會反應(yīng)到Java堆中鼓鲁,形成一塊存儲Object類型所有實例數(shù)據(jù)值的結(jié)構(gòu)化內(nèi)存蕴轨。根據(jù)具體類型以及虛擬機實現(xiàn)的對象內(nèi)存布局的不同,這塊內(nèi)存的長度是不固定的骇吭。
- 在Java堆中還包含能查找到此對象類型數(shù)據(jù)(如對象類型橙弱、父類、實現(xiàn)的接口燥狰、方法等)的地址信息棘脐,這些類型數(shù)據(jù)存儲在方法區(qū)中。
對象訪問方式
reference數(shù)據(jù)類型在Java虛擬機規(guī)范里只規(guī)定了是一個指向?qū)ο蟮囊昧拢]有定義這個引用的實現(xiàn)方式蛀缝。因此,不同虛擬機實現(xiàn)的對象訪問方式會有所不同目代,主流的訪問方式有兩種:
-
使用句柄訪問屈梁。Java堆中將會劃分出一塊內(nèi)存來作為句柄池,reference中存儲的是對象的句柄地址榛了,而句柄中包含了對象實例數(shù)據(jù)和類型數(shù)據(jù)各自的具體地址信息在讶。
image.png -
使用直接指針訪問。reference中存儲的就是對象的地址霜大,而對象中必須考慮如何放置訪問類型數(shù)據(jù)的相關(guān)信息构哺。
image.png
這兩種訪問方式各有優(yōu)勢:
- 使用句柄訪問方式的優(yōu)勢是reference中存儲的是穩(wěn)定的句柄地址,在對象被移動(垃圾收集時移動對象是很普遍的行為)時只會改變句柄中實例數(shù)據(jù)指針战坤,而reference本身不需要被修改曙强。
- 使用直接指針訪問方式的最大好處是速度更快,因為它節(jié)省了一次指針定位的時間開銷途茫。
Sun HotSpot是用直接指針訪問方式進(jìn)行對象訪問的碟嘴。