小小面試一下
前言蜜語
最近馬師傅火的不要不要的令哟,雖然沒有搶到耗子尾汁的商標(biāo)注冊(cè)權(quán),但是必須得蹭一波馬師傅的熱度,下面就是閃電五連鞭的教學(xué)環(huán)節(jié)妨蛹,你準(zhǔn)備好了嗎!
在正式內(nèi)容開始前先甩兩篇關(guān)于類加載機(jī)制和內(nèi)存布局的文章屏富,因?yàn)榻裉斓膬?nèi)容多少與這兩篇文章有直接的聯(lián)系,對(duì)這方面還比較薄弱的朋友可以先看看蛙卤,地址我放在下面狠半。
jvm┃java內(nèi)存區(qū)域,跳槽大廠必會(huì)知識(shí)點(diǎn)!
moon不講武德!!!一個(gè)類加載機(jī)制給面試官說蒙了5溆琛甜滨!
今天本文的內(nèi)容就針對(duì)剛剛模擬面試兩個(gè)問題
1.對(duì)象的創(chuàng)建過程
2.對(duì)象的內(nèi)存布局
對(duì)象的創(chuàng)建過程
以下內(nèi)容基于HotSpot VM 分代模型
這張圖其實(shí)就能完整的說明一個(gè)對(duì)象的創(chuàng)建過程到底發(fā)生了什么,很多朋友可能一下看不懂瘤袖,那么我們就跟著左上角的一步一步來:
-
一個(gè)對(duì)象new出來先判斷線程棧是否能分配下
- 如果能分配下衣摩,直接分配在棧中。
- 如果分配不下則進(jìn)行第二步捂敌。
-
判斷該對(duì)象是否足夠大
- 如果足夠大艾扮,則直接進(jìn)入老年代。
- 如果不夠大占婉,則進(jìn)行第三步泡嘴。
-
判斷創(chuàng)建對(duì)象的線程的TLAB(本地線程緩沖區(qū))空間是否足夠
- 如果足夠,直接分配在TLAB中逆济。
- 如果不夠酌予,則進(jìn)入Eden區(qū)中其他空間。然后進(jìn)行第四步奖慌。
-
GC清除
- 如果清除掉了該對(duì)象抛虫,則直接結(jié)束。
- 如果沒有清除掉對(duì)象简僧,進(jìn)行第5步建椰。
-
此刻對(duì)象進(jìn)入Survivor 1 區(qū),判斷年齡是否足夠大
- 如果年齡足夠大岛马,則直接進(jìn)入old區(qū)域棉姐。
- 如果年齡不夠大,則進(jìn)入Survivor 2 區(qū)啦逆,然后進(jìn)入第4步伞矩,循環(huán)往復(fù)。
通過這張流程圖和步驟解析大家應(yīng)該對(duì)一個(gè)對(duì)象的創(chuàng)建過程有一個(gè)很清晰的概念了夏志,但是其中還是有很多小細(xì)節(jié)會(huì)被忽略扭吁,為什么jvm會(huì)在對(duì)象的創(chuàng)建過程中大作文章,會(huì)分這么多種情況盲镶?為了讓大家更深入的能夠理解它,我們就再來看看下面這幾個(gè)問題:
- 為什么對(duì)象會(huì)選擇先分配在棧中蝌诡?
首先棧是線程私有的,將對(duì)象優(yōu)先分配在棧中,可以通過pop直接將對(duì)象的所有信息,空間直接清除溉贿,當(dāng)線程消亡的時(shí)候也可以直接清理這一塊兒TLAB區(qū)域。
- 為什么jvm會(huì)讓大對(duì)象會(huì)直接進(jìn)入老年代浦旱?
大對(duì)象需要連續(xù)的空間來存儲(chǔ),如果不存入老年代對(duì)jvm說就可能是一個(gè)負(fù)擔(dān)宇色,如果沒有足夠的空間就有可能導(dǎo)致提前觸發(fā)gc來清理空間來安置大對(duì)象。
- 為什么會(huì)選擇先進(jìn)入TLAB?
TLAB是線程本地緩沖區(qū)宣蠕,TLAB的好處就是防止不同線程創(chuàng)建對(duì)象選擇同一塊兒內(nèi)存區(qū)域而產(chǎn)生競(jìng)爭(zhēng)例隆,會(huì)使其概率大大減少。
- 為什么會(huì)有兩個(gè)Survivor區(qū)抢蚀?并且存活且年齡不夠大的對(duì)象會(huì)從一個(gè)Survivor區(qū)轉(zhuǎn)到另一個(gè)Survivor區(qū)镀层?
根據(jù)根可達(dá)算法,jvm會(huì)從開始尋找到所有正在使用的對(duì)象皿曲,沒有使用的就是垃圾,通常情況下唱逢,很多對(duì)象都是用完就拋棄的,所以真正在Survivor區(qū)長(zhǎng)時(shí)間存活的對(duì)象非常少屋休,將這部分對(duì)象從一個(gè)Survivor區(qū)轉(zhuǎn)到另一個(gè)Survivor區(qū)后坞古,就可以直接對(duì)這個(gè)Survivor區(qū)進(jìn)行全量的空間回收了,效率會(huì)很高劫樟。
對(duì)象的內(nèi)存布局
作者可不是標(biāo)題黨痪枫,哈哈,所以我們回到文章的標(biāo)題叠艳,Object o = new Object();到底占用多少個(gè)字節(jié)奶陈?這道題的目的其實(shí)就是考驗(yàn)看你對(duì)對(duì)象的內(nèi)存布局了解的是否清晰,先上圖:
在java中對(duì)象的內(nèi)存布局分為兩種情況虑绵,非數(shù)組對(duì)象和數(shù)組對(duì)象尿瞭,數(shù)組對(duì)象和非數(shù)組對(duì)象的區(qū)別就是需要額外的空間存儲(chǔ)數(shù)組的長(zhǎng)度length。
對(duì)象頭
對(duì)象頭又分為MarkWord和Class Pointer兩部分翅睛。
MarkWord:包含一系列的標(biāo)記位声搁,比如輕量級(jí)鎖的標(biāo)記位,偏向鎖標(biāo)記位,gc記錄信息等等捕发,在32位系統(tǒng)占4字節(jié)疏旨,在64位系統(tǒng)中占8字節(jié)。
ClassPointer:用來指向?qū)ο髮?duì)應(yīng)的Class對(duì)象(其對(duì)應(yīng)的元數(shù)據(jù)對(duì)象)的內(nèi)存地址扎酷。在32位系統(tǒng)占4字節(jié)檐涝,在64位系統(tǒng)中占8字節(jié)。
Length:只在數(shù)組對(duì)象中存在法挨,用來記錄數(shù)組的長(zhǎng)度谁榜,占用4字節(jié)
Instance data
- Instance data:對(duì)象實(shí)際數(shù)據(jù),對(duì)象實(shí)際數(shù)據(jù)包括了對(duì)象的所有成員變量凡纳,其大小由各個(gè)成員變量的大小決定窃植。(這里不包括靜態(tài)成員變量,因?yàn)槠涫窃诜椒▍^(qū)維護(hù)的)
Padding
- Padding:Java對(duì)象占用空間是8字節(jié)對(duì)齊的荐糜,即所有Java對(duì)象占用bytes數(shù)必須是8的倍數(shù),是因?yàn)楫?dāng)我們從磁盤中取一個(gè)數(shù)據(jù)時(shí)巷怜,不會(huì)說我想取一個(gè)字節(jié)就是一個(gè)字節(jié)葛超,都是按照一塊兒一塊兒來取的,這一塊大小是8個(gè)字節(jié)延塑,所以為了完整绣张,padding的作用就是補(bǔ)充字節(jié),保證對(duì)象是8字節(jié)的整數(shù)倍关带。
moon在上文特意標(biāo)注了32位系統(tǒng)和64位系統(tǒng)不同區(qū)域占用空間大小的區(qū)別侥涵,這是因?yàn)?strong>對(duì)象指針在64位JVM下的尋址更長(zhǎng),所以想比32位會(huì)多出來更多占用空間豫缨。
但是現(xiàn)在假設(shè)一個(gè)場(chǎng)景独令,公司現(xiàn)在項(xiàng)目部署的機(jī)器是32位的,你們老板要讓你將項(xiàng)目遷移到64位的系統(tǒng)上好芭,但是又因?yàn)?4位系統(tǒng)比32位系統(tǒng)要多出更多占用空間燃箭,怎么辦,因?yàn)檎碚f我們是不需要這一部分多余空間的舍败,所以jvm已經(jīng)幫你考慮好了招狸,那就是指針壓縮。
指針壓縮
-XX:+UseCompressedOops 這個(gè)參數(shù)就是JVM提供給你的解決方案邻薯,可以壓縮指針裙戏,將占用的空間壓縮為原來的一半,起到節(jié)約空間的作用厕诡,classpointer參數(shù)大小就受到其影響累榜。
Object o = new Object()到底占用多少個(gè)字節(jié)?
通過剛才內(nèi)存布局的學(xué)習(xí)后灵嫌,這個(gè)問題就很好回答了壹罚,面試官其實(shí)就是想問你對(duì)象的內(nèi)存布局是怎樣的,我們這里就針對(duì)這個(gè)問題的結(jié)果分析下寿羞,這里分兩種情況:
在開啟指針壓縮的情況下猖凛,markword占用8字節(jié),classpoint占用4字節(jié)绪穆,Instance data無數(shù)據(jù)辨泳,總共是12字節(jié),由于對(duì)象需要為8的整數(shù)倍玖院,Padding會(huì)補(bǔ)充4個(gè)字節(jié)菠红,總共占用16字節(jié)的存儲(chǔ)空間。
在沒有指針的情況下难菌,markword占用8字節(jié)试溯,classpoint占用8字節(jié),Instance data無數(shù)據(jù)扔傅,總共是16字節(jié)耍共。
結(jié)語
今天的文章和大家介紹了一個(gè)對(duì)象的創(chuàng)建過程,從它的出生到死亡猎塞,都經(jīng)歷了什么试读?也和大家詳細(xì)的說明了對(duì)象的內(nèi)存布局,深入解剖了一下對(duì)象的身體構(gòu)造荠耽,這下面試官再問你钩骇,可就有的聊了,這篇文章的內(nèi)容還是比較肝的铝量,需要大家認(rèn)真閱讀一下倘屹,當(dāng)然,也可以關(guān)注我的公眾號(hào)'moon聊技術(shù)'慢叨,私下聯(lián)系我纽匙,我是moon,下期見~