久久精品精选,精品九九视频,www久久只有这里有精品,亚洲熟女乱色综合一区
    分享

    歲月靜好的一行new Object(),其實(shí)是虛擬機(jī)在為你負(fù)重前行

     jacklopy 2025-09-03

    在Java編程中,我們知道想要得到一個對象的方式很簡單:new Object(),但你知道這樣的歲月靜好,卻總有人(JVM)為我們負(fù)重前行。理解這個過程不僅有助于我們編寫更高效的代碼,也能在遇到內(nèi)存問題時快速定位原因。下面我們就來逐步了解Java對象在虛擬機(jī)(JVM)中創(chuàng)建的完整生命周期。

    一、第一步:類加載檢查 ——"這件商品存在嗎?"

    當(dāng) JVM 執(zhí)行new Object()時,首先要確認(rèn)Object類是否已經(jīng)被加載到內(nèi)存中。這就像我們網(wǎng)購前要先確認(rèn)商品是否在倉庫中存在,JVM 的檢查邏輯可以分為三步:

    類名驗(yàn)證JVM 會從代碼中提取類名 "java.lang.Object",檢查方法區(qū)(JVM 中存儲類信息的內(nèi)存區(qū)域)是否已經(jīng)存在該類的元數(shù)據(jù)(類似商品的說明書)。

    加載缺失類Object類未被加載,JVM 會通過類加載器(ClassLoader)從本地 class 文件或 JAR 包中讀Object.class文件,將其解析為類的元數(shù)據(jù)(包括類的屬性、方法、父類等信息),并存儲到方法區(qū)。
    驗(yàn)證類信息為了確保類文件沒有被篡改,JVM 會對加載Object類進(jìn)行驗(yàn)證,包括字節(jié)碼格式校驗(yàn)、語法檢查等(相當(dāng)于檢查商品包裝是否完好)。

    Object類來說,由于它是 Java 的根類,在 JVM 啟動時就會被提前加載,所以這一步通常會直接跳過加載過程,僅做存在性檢查。但如果是自定義類(new User()),則會完整執(zhí)行上述類加載流程。

    // 第一次使用Object類時觸發(fā)加載Object obj1 = new Object(); // 第二次使用時類已加載,直接復(fù)用Object obj2 = new Object();

    二、第二步:內(nèi)存分配 ——"給商品找個存放的貨架"

    確認(rèn)類已加載后,JVM 需要為新創(chuàng)建Object對象分配內(nèi)存。內(nèi)存大小在類加載階段就已確定(Object類的實(shí)例占用 16 字節(jié),包括對象頭和實(shí)例數(shù)據(jù)),分配過程就像給商品找合適的貨架位置,有兩種常見方式:

    1. 指針碰撞法如果 JVM 的堆內(nèi)存是連續(xù)的(就像一排整齊的貨架),已使用內(nèi)存和空閑內(nèi)存之間有一個指針。分配內(nèi)存時,只需將指針向后移動與對象大小相等的距離(相當(dāng)于把貨架上的分隔板后移)。這種方式高效且無內(nèi)存碎片,但要求堆內(nèi)存必須是連續(xù)的,適合 Serial、ParNew 等收集器。
    1. 空閑列表法如果堆內(nèi)存中存在大量已使用和空閑的內(nèi)存塊(類似雜亂擺放的貨架),JVM 會維護(hù)一張 "空閑列表",記錄所有可用內(nèi)存塊的位置和大小。分配時從列表中找到足夠大的內(nèi)存塊,劃分出對象所需空間后更新列表(相當(dāng)于從雜亂的貨架中找到合適空間放置新商品)。這種方式適合 CMS 等會產(chǎn)生內(nèi)存碎片的收集器。

    在分配內(nèi)存時,JVM 還需要解決多線程并發(fā)問題 —— 避免兩個線程同時分配到同一塊內(nèi)存。就像超市結(jié)賬時需要排隊(duì),JVM 通過兩種方式保證線程安全:要么對內(nèi)存分配過程加鎖(類似排隊(duì)結(jié)賬),要么為每個線程預(yù)先分配一小塊私有內(nèi)存(稱為 TLAB,類似專屬結(jié)賬通道),優(yōu)先在私有內(nèi)存中分配,減少鎖競爭。

    三、第三步:內(nèi)存初始化 ——"給貨架做標(biāo)記"

    內(nèi)存分配完成后,JVM 會將分配到的內(nèi)存空間(除對象頭外)全部初始化為零值(如 0、null、false)。這一步操作就像給新貨架貼上 "未使用" 的標(biāo)簽,確保對象的實(shí)例字段在沒有顯式賦值時,能有一個默認(rèn)的初始值。

    Object對象為例,由于它沒有自定義屬性,這一步會將 16 字節(jié)內(nèi)存中的實(shí)例數(shù)據(jù)部分全部設(shè)為零。如果是自定義類(Userage屬性),則會age的內(nèi)存區(qū)域初始化為 0,避免出現(xiàn)隨機(jī)垃圾值。這也是為什么 Java 中局部變量必須顯式賦值,而類的成員變量可以直接使用的原因? —— 成員變量的默認(rèn)值在這一步已經(jīng)由 JVM 初始化完成。

    四、第四步:設(shè)置對象頭 ——"給商品貼標(biāo)簽"

    內(nèi)存初始化后,JVM 需要給對象設(shè)置 "對象頭"(Object Header),這部分?jǐn)?shù)據(jù)相當(dāng)于商品的標(biāo)簽,記錄了對象的核心信息,主要包括:

    1. 運(yùn)行時元數(shù)據(jù)包含對象的哈希碼(相當(dāng)于商品的唯一編號)、GC 分代年齡(記錄對象存活時間,用于垃圾回收)、鎖狀態(tài)標(biāo)志(是否被線程鎖定)等。
    1. 類型指針指向?qū)ο笏鶎兕惖脑獢?shù)據(jù)在方法區(qū)的地址(相當(dāng)于商品標(biāo)簽上的 "所屬類別",告訴 JVM 這個對象Object類的實(shí)例)。

    Object對象,其對象頭占用 12 字節(jié)(64 位 JVM 默認(rèn)配置),加上 4 字節(jié)的對齊填充(JVM 要求對象大小必須是 8 字節(jié)的整數(shù)倍),總共占用 16 字節(jié)內(nèi)存。

    這就是為什么一個空Object對象會占用 16 字節(jié)內(nèi)存? 

    答: 對象頭和對齊填充已經(jīng)占滿了空間。

    內(nèi)存布局示例

    [對象頭] [實(shí)例數(shù)據(jù)] [對齊填充]| 12字節(jié) |  0字節(jié)  |  4字節(jié)  |

    對象頭變化
    對象頭信息會隨著對象狀態(tài)改變而改變:

    狀態(tài)
    存儲內(nèi)容
    未鎖定
    哈希碼、分代年齡等
    輕量級鎖定
    指向鎖記錄的指針
    重量級鎖定
    指向互斥量的指針
    GC標(biāo)記
    空(不需要記錄信息)

    五、第五步:執(zhí)行構(gòu)造方法 ——"給商品裝內(nèi)容"

    完成對象頭設(shè)置后,JVM 會調(diào)Object類的構(gòu)造方法(<init>()方法)。這一步是真正初始化對象的過程,相當(dāng)于給空貨架填充商品內(nèi)容。

    Object類的構(gòu)造方法非常簡單,沒有實(shí)際邏輯(因?yàn)樗鼪]有需要初始化的屬性)。但如果是自定義類,比User類的構(gòu)造方法需要nameage賦值,那么 JVM 會在這里執(zhí)行相應(yīng)的賦值操作,將具體的值寫入對象的內(nèi)存空間。

    需要注意的是,構(gòu)造方法的執(zhí)行是在類的初始化之后。如果父類還未初始化,JVM 會先觸發(fā)父類的初始化流程(比User類繼Person類,會先執(zhí)Person的構(gòu)造方法),這就是 Java 中 "先有父后有子" 的繼承初始化規(guī)則。

    六、第六步:棧幀引用指向?qū)ο?——"記下藥柜位置"

    當(dāng)對象在堆內(nèi)存中創(chuàng)建完成后,JVM 會將對象的內(nèi)存地址賦值給棧中的引用變量。這就像我們在醫(yī)院取藥時,藥師會告訴我們 "藥品放在 3 號貨架第 2 層",棧中的引用變量就記錄了對象在堆內(nèi)存中的具體位置。

    例如執(zhí)Object obj = new Object()時,"obj" 是棧中的引用變量,new Object()創(chuàng)建的對象在堆內(nèi)存中,執(zhí)行完這行代碼后,obj 會存儲該對象的內(nèi)存地址,后續(xù)通obj.xxx調(diào)用方法時,JVM 就能通過這個地址找到堆中的對象。

    七、第七步:對象可用 ——"商品上架待售"

    經(jīng)過以上六步操作后,Object對象正式創(chuàng)建完成,進(jìn)入可用狀態(tài)。此時 JVM 會繼續(xù)執(zhí)行后續(xù)代碼,對象可以被用來調(diào)用方法(obj.toString())、作為參數(shù)傳遞等。

    當(dāng)這個對象不再被使用(即沒有任何引用指向它),就會被 JVM 的垃圾回收器標(biāo)記為 "可回收",在合適的時機(jī)被清理出內(nèi)存,完成整個生命周期。

    看似平凡的一行代碼,實(shí)則凝聚了 JVM 的設(shè)計(jì)智慧 —— 通過將復(fù)雜的底層操作封裝起來,讓開發(fā)者可以專注于業(yè)務(wù)邏輯,這正是 Java 語言 "一次編寫,到處運(yùn)行" 的魅力所在。

      本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
      轉(zhuǎn)藏 分享 獻(xiàn)花(0

      0條評論

      發(fā)表

      請遵守用戶 評論公約

      類似文章 更多

      主站蜘蛛池模板: 亚洲一区二区偷拍精品| jizz视频在线观看| 国产精品多p对白交换绿帽| 精品中文人妻在线不卡| 国产精品亚洲А∨怡红院| 亚洲综合激情另类小说区| 亚洲欧洲精品日韩av| 天堂久久久久VA久久久久| 色偷偷888欧美精品久久久| 国产日韩入口一区二区| 欧美XXXX黑人又粗又长| 亚洲欧美成人久久一区| 小嫩批日出水无码视频免费 | 亚洲日韩VA无码中文字幕| 国产精品日本一区二区在线播放 | 色噜噜综合亚洲AV中文无码| 国产精品自在线拍国产手机版| 玩弄漂亮少妇高潮白浆| 影音先锋2020色资源网| 亚洲精品无码MV在线观看软件| 2020国产欧洲精品网站| 亚洲综合欧美色五月俺也去| 日韩有码中文字幕国产| 精品无码一区二区三区亚洲桃色| 日韩人妻中文字幕精品| 国产精品国产三级国AV| 久久香蕉国产线看观看怡红院妓院| 久久精品A一国产成人免费网站 | 伊人久久大香线蕉AV五月天| 少妇高潮水多太爽了动态图| 国产偷国产偷亚洲高清人| 久久精品毛片免费观看| 国产精品一区中文字幕| 亚洲另类精品无码专区| 日韩高清亚洲日韩精品一区二区| 欧美亚洲一区二区三区| 成午夜福利人试看120秒| 桃花岛亚洲成在人线AV| 色欲香天天天综合网站无码| 午夜宅男在线永久免费观看网 | 亚洲爆乳WWW无码专区|