資源描述:
《java對(duì)象內(nèi)存結(jié)構(gòu)-java開發(fā)java經(jīng)驗(yàn)技巧》由會(huì)員上傳分享,免費(fèi)在線閱讀,更多相關(guān)內(nèi)容在工程資料-天天文庫。
1、Java對(duì)象內(nèi)存結(jié)構(gòu)-Java開發(fā)Java經(jīng)驗(yàn)技巧Java對(duì)象內(nèi)存結(jié)構(gòu)木文由ImportNew?鄭雯翻譯自codeinstructionso歡迎加入翻譯小組。轉(zhuǎn)載請(qǐng)見文末要求。原文于2008年11月13F1發(fā)表,2008年12月18F1更新:這里還有一篇關(guān)于Java的Sizcof運(yùn)算符的實(shí)用庫的文章。學(xué)C/C++岀身的我,對(duì)Java^j一點(diǎn)非常困惑,那就是缺乏計(jì)算對(duì)象占用內(nèi)存大小的機(jī)制。而在C++中就可以通過sizeof運(yùn)算符來獲得基木類型以及類實(shí)例的大小。C和C++中的這個(gè)操作符對(duì)于指針運(yùn)算、內(nèi)存
2、拷貝和10操作都非常有用。Java中并沒有一個(gè)類似的運(yùn)算符。事實(shí)上,Jova也不需要這種運(yùn)算符。Java中基本類型的大小在語言規(guī)范中已經(jīng)定義了,而C/C++中基本類型大小則跟平臺(tái)相關(guān)。Java冇自己的通過序列化構(gòu)建的10框架。再者,由于Java中沒冇指針,因此指針運(yùn)算和內(nèi)存塊拷貝之類的操作也不存在。但是,Java程序員有吋還是希望能知道一個(gè)Java對(duì)象到底用了多少內(nèi)存的。不過這個(gè)問題的答案并不簡(jiǎn)單。首先要區(qū)分清楚的是shallowsize和deepsize。Shallowsize是指對(duì)象自身占用的內(nèi)
3、存大小,其引用對(duì)象的大小不算在內(nèi)。而deepsize,則是自身所占內(nèi)存大小和其遞歸引用的所有對(duì)象所占內(nèi)存大小的總和。大多數(shù)情況卞,你會(huì)希望獲得一個(gè)對(duì)象的deepsize,但是為了知道這個(gè)值,首先耍知道怎么算shallowsize,下面我來介紹一下。有人抱怨JVM規(guī)范中沒有針對(duì)運(yùn)行時(shí)Java對(duì)象的內(nèi)存結(jié)構(gòu)的說明,這也就是說JVM供應(yīng)商可以按照自己的需要來實(shí)現(xiàn)這一點(diǎn)。后果就是,同一個(gè)類在不同的JVM上運(yùn)行的實(shí)例對(duì)彖占用的內(nèi)存大小會(huì)有差別。好在是世界上大部分人(包括我在內(nèi))都使用SunHotSpot虛擬機(jī)
4、,這就大大簡(jiǎn)化了這個(gè)問題。我們接下來的討論也會(huì)基于32位的Sun公司的JVM。下面我介紹一?些規(guī)則來輔助解釋JVM如何組織對(duì)象在內(nèi)存中的布局的。沒有實(shí)例屬性的類的內(nèi)存布局在SunJVM中,(除了數(shù)組Z外的)對(duì)象都有兩個(gè)機(jī)器字(words)的頭部。第一個(gè)字中包含這個(gè)對(duì)象的標(biāo)示哈希碼以及其他一些類似鎖狀態(tài)和等標(biāo)識(shí)信息,第二個(gè)字中包含一個(gè)指向?qū)ο蟮念惖囊谩A硗?,任何?duì)象都是8個(gè)字節(jié)為粒度進(jìn)行對(duì)齊的。這就是對(duì)彖內(nèi)存布局的第一個(gè)規(guī)則:規(guī)則1:任何對(duì)彖都是8個(gè)字節(jié)為粒度進(jìn)行對(duì)齊的。比如,如果調(diào)用newObje
5、ct(),由Object類并沒有其他沒冇其他可存儲(chǔ)的成員,那么僅僅使用堆中的8個(gè)字節(jié)來保存兩個(gè)字的頭部即可。繼承了Object的類的內(nèi)存布局除了上面所說的8個(gè)字節(jié)的頭部,類屬性緊隨其后。屬性通常根據(jù)其人小來排列。例如,整型(int)以4個(gè)字節(jié)為單位對(duì)齊,長(zhǎng)整型(long)以8個(gè)字節(jié)為單位對(duì)齊。這里是出丁?性能考慮而這么設(shè)計(jì)的:通常情況下,如呆數(shù)據(jù)以4字節(jié)為單位對(duì)齊,那么從內(nèi)存中讀4字節(jié)的數(shù)據(jù)并寫入到處理器的4字節(jié)寄存器是性價(jià)比更高的。為了節(jié)省內(nèi)存,SunVM并沒有按照屬性聲明時(shí)的順序來進(jìn)行內(nèi)存布局。
6、實(shí)際上,厲性在內(nèi)存中按照下面的順序來組織:1.雙精度型(doubles)和長(zhǎng)整型(longs)2.整型(ints)和浮點(diǎn)型(floats)3.短整型(shorts)和字符型(chars)4.布爾型(booleans)和字節(jié)型(bytes)5.引用類型(references)內(nèi)存使用率會(huì)通過這個(gè)機(jī)制得到優(yōu)化。例如,如下聲明一個(gè)類:classMyClass{bytea;intc;booleand;longe;Objectf;}如果JVM并沒冇打亂屈性的聲明順序,其對(duì)象內(nèi)存布局將會(huì)是下而這個(gè)樣子:[HEA
7、DER:8bytes]8[a:1byte]9[padding:[c:[d:[padding:[e:[f:[padding:3bytes]124bytes]161byte]177bytes]248bytes]324bytes]364bytes]40[HEADER:[e:[c:[a:[d:[padding:[f:[padding:8bytes]8bytes]4bytes]1byte]1byte]2bytes]4bytes]4bytes]816202122242832此吋,用丁?山位的14個(gè)字節(jié)是浪費(fèi)的,
8、這個(gè)對(duì)象一共使用了40個(gè)字節(jié)的內(nèi)存空間。但是,如果用上面的規(guī)則對(duì)這些對(duì)象重新排序,其內(nèi)存結(jié)果會(huì)變成下面這個(gè)樣子:這次,用于占位的只有6個(gè)字節(jié),這個(gè)對(duì)象使用了32個(gè)字節(jié)的內(nèi)存空間。因此,對(duì)彖內(nèi)存布局的第二個(gè)規(guī)則是:規(guī)則2:類屬性按照如卜?優(yōu)先級(jí)進(jìn)行排列:長(zhǎng)整型和雙粋度類型;整型和浮點(diǎn)型;字符和短整型;字節(jié)類世和布爾類黑,最后是引用類型,這些屈性都按照各自的單位對(duì)齊?,F(xiàn)在我們知道如何計(jì)算一個(gè)繼承了Object的類的實(shí)例的內(nèi)存大小了。下面這個(gè)例子用來做下練習(xí):java.la