對象的內(nèi)存布局
- 在HotSpot虛擬機(jī)中,對象在內(nèi)存中存儲(chǔ)的布局可以分為3塊區(qū)域:對象頭(Header)、實(shí)例數(shù)據(jù)(Instance Data)、對齊填充(Padding)。
- 對象頭包括兩部分信息:
- 第一部分用于存儲(chǔ)對象的自身的運(yùn)行時(shí)數(shù)據(jù),如哈希碼(HashCode)、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID等。
- 第二部分是類型指針,即對象指向它的類元數(shù)據(jù)(存放在方法區(qū))的指針,虛擬機(jī)通過這個(gè)指針來確定這個(gè)對象是哪個(gè)類的實(shí)例。
- 對象頭包括兩部分信息:
- 實(shí)例數(shù)據(jù)部分:是對象真正存儲(chǔ)的有效信息,也是在程序代碼中所定義的各種類型的字段內(nèi)容。無論是從父類繼承下來的,還是在子類中定義的,都需要記錄起來。
- 對齊填充:略。
對象的訪問定位
概述:建立對象是為了使用對象,我們的Java程序需要通過棧上的reference數(shù)據(jù)來操作堆上的具體對象。目前主流的訪問方式有使用句柄和直接指針兩種。
- 直接指針訪問方式的最大好處就是速度更快,它節(jié)省了一次指針定位的時(shí)間開銷,由于對象的訪問在Java中非常頻繁,HotSpot采用的便是這種方式。
- 下圖即為Java利用直接指針訪問對象:
Paste_Image.png
實(shí)例分析###
public class Dog{
private int age;
public Dog() {
}
public Dog(int age){
this.age = age;
}
public int getAge() {
return age;
}
public static void main(String[] args) {
Dog dog = new Dog();
...
}
}
- 內(nèi)存分配圖如下
Paste_Image.png
- 重點(diǎn)內(nèi)容說明
- 構(gòu)造方法or實(shí)例方法:需要將this指針(即對象地址),傳遞進(jìn)方法內(nèi),才可以訪問屬性,即才知道訪問哪一個(gè)對象的屬性。這才是方法內(nèi)為什么會(huì)隱含一個(gè)this指針。
- 靜態(tài)方法:由于靜態(tài)方法內(nèi)不允許含有對象屬性,因此應(yīng)該不含有this指針。這和構(gòu)造方法是不同的,我也一直對《Thinking in Java》所提到的:“構(gòu)造方法應(yīng)該隱含是靜態(tài)的”,持有疑問態(tài)度,雖然某些角度看,兩者有相似的地方,但是從大部分方面看都是不同的。
- 調(diào)用構(gòu)造方法不一定會(huì)創(chuàng)建對象,但是調(diào)用構(gòu)造方法可以初始化對象。最強(qiáng)有力的證明就是new子類對象的時(shí)候肯定會(huì)調(diào)用父類對象的構(gòu)造方法,但是并不會(huì)創(chuàng)建父類對象。虛擬機(jī)只有接收到new指令的時(shí)候,才會(huì)真正的去創(chuàng)建父類對象。
好了,最后打住收工,啊彌陀否!!!