偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

HotSpot虛擬機(jī)對(duì)象探秘:對(duì)象的創(chuàng)建,我居然看懂了!

云計(jì)算 虛擬化
就這一句,貌似平平無奇,但你有沒有想過,JVM 背后都悄咪咪做了些什么?對(duì)象是怎么一步一步,從“無中生有”被變出來的?HotSpot 是怎么分配內(nèi)存、初始化、搞定 header 的?

引言

大家好,我是你們的老朋友小米,一個(gè)每天都在代碼與咖啡之間切換狀態(tài)的 31 歲程序員。

今天這篇文章,我想帶你一起走進(jìn) Java 世界中一個(gè)特別“魔幻”的角落——對(duì)象創(chuàng)建。

這個(gè)話題你肯定不陌生,對(duì)吧?我們平時(shí)寫代碼:

圖片

就這一句,貌似平平無奇,但你有沒有想過,JVM 背后都悄咪咪做了些什么?對(duì)象是怎么一步一步,從“無中生有”被變出來的?HotSpot 是怎么分配內(nèi)存、初始化、搞定 header 的?

今天,小米就帶你走進(jìn) HotSpot 的幕后舞臺(tái),一探對(duì)象創(chuàng)建的秘密。

一切從 new 開始,但 new 只是個(gè)“開關(guān)”

那天我正和同事阿剛喝著下午茶,聊著最近項(xiàng)目優(yōu)化的事,他突然拋來一句:

“你知道 JVM 是怎么創(chuàng)建一個(gè) Java 對(duì)象的嗎?”

當(dāng)時(shí)我一愣,心里想著不就 new 一下嘛,還能有啥。

但等他掏出一張紙開始畫圖的時(shí)候,我才知道,我懂得還遠(yuǎn)遠(yuǎn)不夠。

其實(shí)當(dāng)我們寫下 new User() 這句代碼時(shí),Java 編譯器做的只是把它編譯成了一條字節(jié)碼指令:new。

而真正的魔術(shù),是在 HotSpot 虛擬機(jī)執(zhí)行字節(jié)碼時(shí)才開始的。

這就好比你按下了電梯按鈕,電梯是不是真的來,還得看調(diào)度系統(tǒng)是不是給你安排得當(dāng)。

HotSpot對(duì)象創(chuàng)建的五個(gè)階段,就像造房子

阿剛給我講了一個(gè)特別形象的比喻,他說 JVM 創(chuàng)建對(duì)象就像造房子,大致可以拆解為這五個(gè)步驟:

  • 類加載檢查(確定圖紙是否有)
  • 內(nèi)存分配(拿地皮)
  • 內(nèi)存初始化(打地基)
  • 設(shè)置對(duì)象頭(裝修主體)
  • 執(zhí)行構(gòu)造方法(軟裝上線)

我當(dāng)時(shí)猛點(diǎn)頭,這不就是咱寫代碼時(shí)那句 new 背后的隱藏劇本嗎!

下面我就一個(gè)個(gè)來講,保證你聽完之后也能在面試官面前吹爆 JVM 對(duì)象創(chuàng)建流程。

第一步:類加載檢查,圖紙有沒有?

每次 new 一個(gè)對(duì)象,JVM 的第一反應(yīng)是:這個(gè)類我加載過沒?

HotSpot 會(huì)通過類加載子系統(tǒng)去檢查類的元數(shù)據(jù)是否已經(jīng)加載、初始化過。

如果沒有?那就先通過雙親委派模型把這個(gè)類加載進(jìn)來。別忘了,類的元信息是在 方法區(qū)(或說元空間 Metaspace) 里的。

沒有圖紙,房子肯定不能造,對(duì)吧。

第二步:內(nèi)存分配,拿地皮

這個(gè)階段,HotSpot 要為新對(duì)象劃一塊地盤,也就是在堆內(nèi)存中“圈一塊地”。

它有兩種分配方式,分別叫做:

  • 指針碰撞(bump the pointer)
  • 空閑列表(free list)

如果堆內(nèi)存是規(guī)整的,也就是已經(jīng)整理過、不會(huì)有內(nèi)存碎片,JVM 就直接通過一個(gè)叫 alloc_ptr 的指針往前一推,一口氣分配下一塊內(nèi)存,效率超高。

如果堆是不規(guī)整的(比如用了 CMS 垃圾收集器),那 JVM 就得在內(nèi)存中找一個(gè)合適的空閑塊,效率會(huì)稍慢。

但這還不夠,JVM 還得保證線程安全——畢竟多線程下好幾個(gè)線程都可能在同時(shí) new 對(duì)象啊。

于是,它用上了三板斧:

  • 通過加鎖(如 TLAB 鎖)
  • 通過原子指令 CAS + 重試
  • 使用線程本地分配緩沖(TLAB)

大多數(shù)時(shí)候,我們的對(duì)象是在 TLAB(Thread Local Allocation Buffer) 中分配的,線程獨(dú)占,不用加鎖,效率拉滿。

第三步:內(nèi)存初始化,打地基

拿到了地皮之后,HotSpot 下一步就是“清地基”——也就是把剛分配的內(nèi)存區(qū)域清零。

這一步很關(guān)鍵,如果不清零,那對(duì)象的字段可能全是垃圾值,后面出 bug 可就一發(fā)不可收拾了。

清零完畢后,JVM 知道這塊內(nèi)存已經(jīng)是“干凈的”,可以用來創(chuàng)建對(duì)象了。

第四步:設(shè)置對(duì)象頭,裝修主體

HotSpot 中的每個(gè)對(duì)象,都不是裸奔的,它的前面都帶著一個(gè)“對(duì)象頭”。

這個(gè)對(duì)象頭包含了兩類信息:

  • Mark Word(標(biāo)記字段):用于存儲(chǔ)對(duì)象的哈希碼、GC 分代年齡、鎖信息等等。
  • Klass Pointer:指向?qū)ο笏鶎俚念惖脑獢?shù)據(jù)。

JVM 會(huì)把這些信息填充進(jìn)去,就像把房子主體的水電管線都布好。

這一步結(jié)束,對(duì)象就有了“身份”和“結(jié)構(gòu)”。

第五步:執(zhí)行構(gòu)造方法,軟裝上線

最后一步才是我們 Java 程序員最熟悉的一步:

圖片圖片

JVM 會(huì)根據(jù)類的構(gòu)造函數(shù),逐一執(zhí)行初始化代碼,比如字段賦值、初始化列表等。

這一步,就是給房子裝上窗簾、沙發(fā)、燈具——真正成為一個(gè)“能住人”的家。

“new”背后的思考:為什么你要懂這些?

聽完阿剛那天的分享,我感觸特別深:

我們平時(shí)太容易把對(duì)象創(chuàng)建當(dāng)成“理所當(dāng)然”,卻沒意識(shí)到背后是一套精密的設(shè)計(jì)和優(yōu)化。

尤其在高并發(fā)、內(nèi)存敏感的業(yè)務(wù)場景下,理解對(duì)象創(chuàng)建過程能幫你:

  • 識(shí)別性能瓶頸(比如頻繁 GC 的根源可能是對(duì)象創(chuàng)建太多)
  • 更高效地使用 TLAB 與逃逸分析
  • 編寫更貼合 JVM 優(yōu)化路徑的代碼

比如:用對(duì)象池復(fù)用對(duì)象、避免創(chuàng)建臨時(shí)對(duì)象、使用基本類型替代包裝類型等等。

對(duì)象創(chuàng)建的“高級(jí)玩法”:逃逸分析與棧上分配

其實(shí) HotSpot 還會(huì)進(jìn)一步優(yōu)化對(duì)象的創(chuàng)建,比如當(dāng) JVM 發(fā)現(xiàn)某個(gè)對(duì)象 沒有逃出當(dāng)前方法 時(shí),它甚至?xí)苯釉跅I戏峙鋵?duì)象,而不是堆中。

這叫做:逃逸分析(Escape Analysis)

如果逃逸分析判斷對(duì)象“只在方法內(nèi)部用”,那它就不用堆內(nèi)存了,直接在棧中分配,效率更高,GC 也不會(huì)管它。

你想啊,這對(duì)象一用完方法就銷毀了,壓根不用等 GC。

還有一種優(yōu)化方式叫做:標(biāo)量替換,JVM 會(huì)把整個(gè)對(duì)象拆成若干個(gè)字段來優(yōu)化分配,用得更靈活。

這些優(yōu)化,都得益于你理解對(duì)象是怎么創(chuàng)建的,才能在實(shí)際項(xiàng)目中利用起來。

總結(jié)

說到這,你會(huì)發(fā)現(xiàn),對(duì)象的創(chuàng)建遠(yuǎn)比你想象中復(fù)雜,但每一個(gè)步驟都是為了性能、并發(fā)、安全做出妥協(xié)和平衡。

讓我再用建房子的比喻總結(jié)一次對(duì)象創(chuàng)建的五大步驟:

  • 看圖紙(類加載檢查)
  • 拿地皮(內(nèi)存分配)
  • 打地基(內(nèi)存清零)
  • 裝修主體(設(shè)置對(duì)象頭)
  • 上軟裝(執(zhí)行構(gòu)造函數(shù))

如果你能理解這些流程,相信在調(diào)優(yōu)性能、理解內(nèi)存問題、寫出更高質(zhì)量代碼時(shí),你會(huì)有意想不到的收獲。

最后,給你一個(gè)小問題

在 JVM 中,如果你創(chuàng)建了 100 萬個(gè)小對(duì)象,它們都短生命周期、只在方法里用,你會(huì)如何優(yōu)化它?

責(zé)任編輯:武曉燕 來源: 軟件求生
相關(guān)推薦

2025-01-24 00:00:00

JavaHotSpot虛擬機(jī)

2020-04-01 22:05:24

虛擬機(jī)HotSpotJava

2010-11-05 09:47:11

OracleJava虛擬機(jī)

2012-08-06 09:26:19

Java虛擬機(jī)垃圾回收

2021-09-10 00:34:22

Java 線程啟動(dòng)

2024-09-30 16:08:43

Python虛擬機(jī)棧幀

2010-03-10 10:03:10

Python對(duì)象體系

2021-07-30 07:22:51

JVM虛擬機(jī)棧 Stack

2020-09-02 07:03:04

虛擬機(jī)HotSpotJava

2010-02-24 16:37:27

Ubuntu VMwa

2023-03-03 08:10:15

TerraformAzure虛擬機(jī)

2013-01-18 14:04:58

VMwareWorkstation

2020-04-22 21:44:18

Java虛擬機(jī)算法

2017-03-06 09:32:50

CephKVM虛擬機(jī)

2020-04-09 11:00:20

Java虛擬機(jī)對(duì)象

2010-06-22 09:40:38

PHP方法重載

2012-05-18 10:22:23

2011-05-05 09:32:59

CentOS 5.6KVM

2020-01-17 10:52:37

無服務(wù)器容器技術(shù)

2021-11-19 14:11:49

虛擬機(jī)QuickguiLinux
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)