對象如何訪問
之前的文章中,介紹過Java虛擬機棧的知識。
在Java虛擬機棧中,每個線程執(zhí)行一個方法時,都會創(chuàng)建一個棧幀,棧幀用于存儲這個方法的一些信息,其中包括局部變量表,也就是該方法中用到了哪些局部變量。
局部變量表存儲了編譯期可知的基本數據類型(boolean int double等)、引用數據類型(創(chuàng)建的對象)和returnAddress類型(指向一條指令,方法執(zhí)行完后要做什么)。每個局部變量都會占用1個局部變量空間(double和long類型會占用2個局部變量空間),簡稱為Slot。
其中,引用數據類型就跟我們今天要說的對象的訪問定位有關。
在我們程序方法中,我們通過new的方式來創(chuàng)建一個對象。創(chuàng)建的對象保存在Java堆中,而創(chuàng)建的變量保存在Java棧里。那么,當我們程序實際使用到該對象時,該如何去訪問堆中的對象呢?
Java程序通過棧上的reference(局部變量)數據來操作堆中具體的對象,reference(局部變量)數據中保存這堆中對象的引用,但是Java虛擬機規(guī)范中并沒有告知該引用以何種方式去定位、去訪問堆中對象的具體位置。
目前,主流的訪問方式有:使用句柄和直接指針。
使用句柄
使用句柄來訪問的話,Java堆中會劃分出一塊內存用作句柄池,reference中存儲的就是對象的句柄地址,而句柄中實際上包含了對象的實例數據與類型數據各自具體的地址信息。
畫個圖,更明確的表達下:

直接指針
使用直接指針訪問的話,reference中存儲的就是對象的實際內存地址,不過在Java堆中的對象需要考慮如何去存儲類型數據的信息。
畫個圖,更明確的表達下:

對于這兩種方式來說,具體使用哪一種,由實際的虛擬機決定。就HotSpot來說,使用的是直接指針形式來實現對對象的訪問。
不過,就這兩種方式來說,各有各的優(yōu)勢。使用句柄的好處,就是當實際對象被移動時,棧幀中的指向無需改變,只需要修改句柄中的指向即可,棧幀中的變量存儲這穩(wěn)定的內存地址。
直接指針的好處,是棧幀中的變量直接指向了Java堆中實際的內存地址,訪問速度更快,節(jié)省了一次指針定位的時間開銷。

京東購買鏈接:可伸縮服務架構-框架與中間件