溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java對象由什么組成

發(fā)布時(shí)間:2022-02-07 14:58:27 來源:億速云 閱讀:267 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“Java對象由什么組成”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“Java對象由什么組成”吧!

    Java對象保存在內(nèi)存中時(shí),由以下三部分組成:

    1,對象頭

    2,實(shí)例數(shù)據(jù)

    3,對齊填充字節(jié)

    一,對象頭

    java的對象頭由以下三部分組成:

    Java對象由什么組成

    1,Mark Word

    2,指向類的指針

    3,數(shù)組長度(只有數(shù)組對象才有)

    對象頭分為三個(gè)部分:

    一、Mark Word部分,從名字就能知道它是一個(gè)記錄和描述對象的部分。這也是我接下來主要講解的部分,因?yàn)槠渌膬?nèi)容,基本沒有多大的變化情況。占八字節(jié)內(nèi)存。

    二、類型指針部分,也叫元數(shù)據(jù)指針什么的,主要是存儲元數(shù)據(jù)的地址,對于對象的類型信息,指向方法區(qū)的類信息部分,對于對象的成員變量部分,基本類型就指向方法區(qū)的運(yùn)行時(shí)常量池,String類型指向在jdk1.7之后從方法區(qū)移到堆區(qū)的字符串常量池,其他的對象類型,則指向堆區(qū)的對象存儲地址。占八字節(jié)內(nèi)存,jvm有默認(rèn)開啟指針壓縮,因?yàn)榘l(fā)現(xiàn)類型指針部分用不了64位那么多,所以被指針壓縮后,成為了四字節(jié),指針壓縮的原理,這里我就不說了,非本文重點(diǎn)。

    三、數(shù)組數(shù)據(jù)部分,專門用來存儲數(shù)組數(shù)據(jù)。

    1,Mark Word

    Mark Word記錄了對象和鎖有關(guān)的信息,當(dāng)這個(gè)對象被synchronized關(guān)鍵字當(dāng)成同步鎖時(shí),圍繞這個(gè)鎖的一系列操作都和Mark Word有關(guān)。

    Mark Word在32位JVM中的長度是32bit,在64位JVM中長度是64bit。

    Mark Word在不同的鎖狀態(tài)下存儲的內(nèi)容不同,在32位JVM中是這么存的:

    鎖狀態(tài)

    25bit

    4bit

    1bit

    2bit

    23bit

    2bit

    是否偏向鎖

    鎖標(biāo)志位

    無鎖

    對象的HashCode

    分代年齡

    0

    01

    偏向鎖

    線程ID

    Epoch

    分代年齡

    1

    01

    輕量級鎖

    指向棧中鎖記錄的指針

    00

    重量級鎖

    指向重量級鎖的指針

    10

    GC標(biāo)記

    11

    其中無鎖和偏向鎖的鎖標(biāo)志位都是01,只是在前面的1bit區(qū)分了這是無鎖狀態(tài)還是偏向鎖狀態(tài)。

    JDK1.6以后的版本在處理同步鎖時(shí)存在鎖升級的概念,JVM對于同步鎖的處理是從偏向鎖開始的,隨著競爭越來越激烈,處理方式從偏向鎖升級到輕量級鎖,最終升級到重量級鎖。

    JVM一般是這樣使用鎖和Mark Word的:

    1,當(dāng)沒有被當(dāng)成鎖時(shí),這就是一個(gè)普通的對象,Mark Word記錄對象的HashCode,鎖標(biāo)志位是01,是否偏向鎖那一位是0。

    2,當(dāng)對象被當(dāng)做同步鎖并有一個(gè)線程A搶到了鎖時(shí),鎖標(biāo)志位還是01,但是否偏向鎖那一位改成1,前23bit記錄搶到鎖的線程id,表示進(jìn)入偏向鎖狀態(tài)。

    3,當(dāng)線程A再次試圖來獲得鎖時(shí),JVM發(fā)現(xiàn)同步鎖對象的標(biāo)志位是01,是否偏向鎖是1,也就是偏向狀態(tài),Mark Word中記錄的線程id就是線程A自己的id,表示線程A已經(jīng)獲得了這個(gè)偏向鎖,可以執(zhí)行同步鎖的代碼。

    4,當(dāng)線程B試圖獲得這個(gè)鎖時(shí),JVM發(fā)現(xiàn)同步鎖處于偏向狀態(tài),但是Mark Word中的線程id記錄的不是B,那么線程B會先用CAS操作試圖獲得鎖,這里的獲得鎖操作是有可能成功的,因?yàn)榫€程A一般不會自動釋放偏向鎖。如果搶鎖成功,就把Mark Word里的線程id改為線程B的id,代表線程B獲得了這個(gè)偏向鎖,可以執(zhí)行同步鎖代碼。如果搶鎖失敗,則繼續(xù)執(zhí)行步驟5。

    5,偏向鎖狀態(tài)搶鎖失敗,代表當(dāng)前鎖有一定的競爭,偏向鎖將升級為輕量級鎖。JVM會在當(dāng)前線程的線程棧中開辟一塊單獨(dú)的空間,里面保存指向?qū)ο箧iMark Word的指針,同時(shí)在對象鎖Mark Word中保存指向這片空間的指針。上述兩個(gè)保存操作都是CAS操作,如果保存成功,代表線程搶到了同步鎖,就把Mark Word中的鎖標(biāo)志位改成00,可以執(zhí)行同步鎖代碼。如果保存失敗,表示搶鎖失敗,競爭太激烈,繼續(xù)執(zhí)行步驟6。

    6,輕量級鎖搶鎖失敗,JVM會使用自旋鎖,自旋鎖不是一個(gè)鎖狀態(tài),只是代表不斷的重試,嘗試搶鎖。從JDK1.7開始,自旋鎖默認(rèn)啟用,自旋次數(shù)由JVM決定。如果搶鎖成功則執(zhí)行同步鎖代碼,如果失敗則繼續(xù)執(zhí)行步驟7。

    7,自旋鎖重試之后如果搶鎖依然失敗,同步鎖會升級至重量級鎖,鎖標(biāo)志位改為10。在這個(gè)狀態(tài)下,未搶到鎖的線程都會被阻塞。

    2,指向類的指針

    該指針在32位JVM中的長度是32bit,在64位JVM中長度是64bit。

    Java對象的類數(shù)據(jù)保存在方法區(qū)。

    3,數(shù)組長度

    只有數(shù)組對象保存了這部分?jǐn)?shù)據(jù)。

    該數(shù)據(jù)在32位和64位JVM中長度都是32bit。

    二,實(shí)例數(shù)據(jù)

    對象的實(shí)例數(shù)據(jù)就是在java代碼中能看到的屬性和他們的值。

    三,對齊填充字節(jié)

    因?yàn)镴VM要求java的對象占的內(nèi)存大小應(yīng)該是8bit的倍數(shù),所以后面有幾個(gè)字節(jié)用于把對象的大小補(bǔ)齊至8bit的倍數(shù),沒有特別的功能。

    到此,相信大家對“Java對象由什么組成”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI