【2】JVM-JAVA對象的訪問
Java中對象的訪問
JAVA是面向對象的語言,那麽在JAVA虛擬機中,存在非常多的對象,對象訪問是無處不在的。即時是最簡單的訪問,也會涉及到JAVA棧、JAVA堆、方法區這三個非常重要的內存區域之間的關聯關系。
比如:
Object obj = new Object();
其中,“Object obj”這部分語義作為一個reference類型數據出現,將存儲到JAVA棧的本地變量表中。new Object()將生成一個實體對象,存儲在JAVA堆中,包含了Object類型的所有實例數據值(對象中各個字段的數據)的結構化內存,根據具體類型以及虛擬機實現的對象內存布局的不同,這塊內存的長度是不固定的。另外,在JAVA堆中還必須包含能查找到此對象類型數據(如對象類型、父類、實現接口、方法等)的地址信息,這些類型數據存儲在方法區中。
由於reference類型在JAVA虛擬機規範裏面只規定了一個指向對象的引用,並沒有定義這個引用該通過哪種方式去定位,以及訪問到JAVA堆中的對象的具體位置,因此不同虛擬機實現的對象訪問方式會有所不同,主流的訪問方式有兩種:句柄和直接指針。
- 句柄
JAVA堆中將會劃分出來一塊內存作為句柄池,reference中就是存儲了對象的句柄地址,而句柄中包含了對象實例數據和類型數據各自的具體地址信息。
使用句柄訪問的最大好處是reference中存儲的是穩定的句柄地址,在對象被移動時,只會改變句柄中的實例數據指針,而reference本身不需要被修改。
- 直接指針
相比較句柄的訪問方式,JAVA堆中不會單獨劃分內存,reference中直接存儲了對象地址,而對象中包含了對象類型數據的地址信息。
使用直接指針的最大好處就是速度更快,節省了一次指針定位需要的時間開銷,由於JAVA對象訪問十分頻繁,這類開銷積小成多後也是一項非常可觀的執行成本。Sun HotSpot虛擬機使用的就是這種訪問方式。
一個實體類,名為Stu:
[html] view plain copy print?
- public class Stu extends Object{
- private String name;
- private int age;
- public Stu(String name,String age){
- this.name = name;
- this.age = age;
- }
- public String getName(){
- return this.name;
- }
- ...
- }
創建Stu對象:
Stu kevin = new Stu(“kevin”,15);
這樣根據上文解釋如下:
kevin作為一個reference類型的變量存儲在本地變量表中,在hot spot虛擬機中,存儲的是(kevin=)具體對象的直接地址;new Stu(“kevin”,15)就是實例化了一個對象,JAVA堆中Stu實體類的所有的字段信息,比如name=”kevin”,age=15。此時,JAVA堆中還存儲了Stu對象的類型數據的地址信息,通過這個地址在方法區中可以查找對象的類型、父類、實現的接口、方法等信息。
【2】JVM-JAVA對象的訪問