這篇文章將為大家詳細(xì)講解有關(guān)如何解密Java對象,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識(shí)有一定的了解。
澄江ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場景,ssl證書未來市場廣闊!成為創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:028-86922220(備注:SSL證書合作)期待與您的合作!
在Java程序運(yùn)行過程中時(shí)時(shí)刻刻都有對象被創(chuàng)建出來,對象的創(chuàng)建方式有很多種,最常見的就是new,其次還有clone和反序列化。下面我們一起來解密對象的創(chuàng)建、內(nèi)存布局以及如何定位一個(gè)對象。
當(dāng)我們在創(chuàng)建對象時(shí),首先會(huì)檢查創(chuàng)建對象的類能否在常量池中定位到符號(hào)引用,并檢查符號(hào)引用代表的類是否被加載、解析和初始化過,如果沒有則必須執(zhí)行相應(yīng)的類加載過程(這個(gè)后面也會(huì)單獨(dú)寫一篇文章講解)。
對象創(chuàng)建的過程大約有以下幾步:
為對象分配內(nèi)存本質(zhì)上就是從Java堆中劃分出一塊固定大小的內(nèi)存給Java對象使用。對象內(nèi)存分配主要有兩種:
具體使用哪種方式取決于堆內(nèi)存是否工整,堆內(nèi)存是否工整本質(zhì)又取決于垃圾回收器是否帶有壓縮整理功能。
指針碰撞的分配方式用于在內(nèi)存工整的堆中進(jìn)行對象分配,所有被使用的內(nèi)存放在一邊,未被使用的在另一邊,中間放著一個(gè)指針作為分界點(diǎn)的指示器,當(dāng)為對象分配內(nèi)存時(shí),只需要將指針往未被使用的一邊挪動(dòng)與對象相等大小的距離就可以。
空閑列表適合在不規(guī)整的內(nèi)存中為對象分配內(nèi)存,虛擬機(jī)為了知道哪些內(nèi)存區(qū)域可用,必須維護(hù)一個(gè)列表,當(dāng)進(jìn)行內(nèi)存分配時(shí),則在列表中選取一個(gè)足夠大的空間劃分給對象使用。
對象分配在虛擬機(jī)中的分配并不是線程安全的,為了解決這個(gè)問題,主要有兩種解決方法:
對象在內(nèi)存中的布局主要有三塊:
對象頭主要用來存儲(chǔ)兩塊信息:
對象自身運(yùn)行時(shí)的數(shù)據(jù)主要包括:哈希碼、GC分代年齡、鎖狀態(tài)標(biāo)志、線程持有的鎖、偏向線程ID、偏向時(shí)間戳等。這部分?jǐn)?shù)據(jù)的長度在32位和64位的虛擬機(jī)(未開啟壓縮指針)中分別為32位和64位。
存儲(chǔ)內(nèi)容 | 標(biāo)志位 | 狀態(tài) |
---|---|---|
對象哈希碼、對象分代年齡 | 01 | 未鎖定 |
指向鎖記錄的指針 | 00 | 輕量級(jí)鎖定 |
指向重量級(jí)鎖的指針 | 10 | 膨脹(重量級(jí)鎖定) |
空,不需要記錄信息 | 11 | GC標(biāo)記 |
偏向線程ID、偏向時(shí)間戳、對象分代年齡 | 01 | 可偏向 |
類型指針可以用來確定這個(gè)對象是哪個(gè)類的實(shí)例,但虛擬機(jī)的實(shí)現(xiàn)不是必須在對象上保留類型指針。
實(shí)例數(shù)據(jù)是對象真正存儲(chǔ)的有效信息,就是代碼中各種類型字段的內(nèi)容,無論是從父類還是子類中定義的,內(nèi)容存儲(chǔ)的順序會(huì)受到虛擬機(jī)分配策略參數(shù)和字段在Java源碼中定義順序的影響。但是相同寬度的字段會(huì)分配到一起,在這個(gè)前提條件下,子類較窄的變量會(huì)插到父類變量的空隙之中。
對齊填充并不是必然存在,由于虛擬機(jī)的內(nèi)存管理要求對象其實(shí)地址必須是8字節(jié)的整數(shù)倍,也就是對象大小必須是8字節(jié)的整數(shù)倍,因此當(dāng)對象實(shí)例不是8字節(jié)的整數(shù)倍大小時(shí),需要通過對齊填充補(bǔ)全。
對象建立以后我們需要使用它,我們可以通過Java棧上的reference來操作堆上的具體對象,但是如何通過reference來找到具體的對象則是需要我們?nèi)ソ鉀Q的,目前主要有兩種方式:
下圖是采用句柄的方式去訪問對象
下圖是采用直接指針的方式去訪問對象
通過上述兩種圖的對比,我們可以看出句柄的優(yōu)勢在于棧中的reference存儲(chǔ)的內(nèi)容是穩(wěn)定的句柄地址,不會(huì)因?yàn)閷ο蟮囊苿?dòng)而改變,但訪問會(huì)遜于直接指針,因?yàn)槎嗔艘淮沃羔樁ㄎ坏臅r(shí)間開銷。
直接指針的訪問方式的最大好處就是速度快,節(jié)省了一次指針定位的時(shí)間開銷。
關(guān)于如何解密Java對象就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。