JVM对象占用内存计算
大家都知道,jvm中對(duì)象實(shí)例存儲(chǔ)在堆中,對(duì)象的引用存儲(chǔ)在棧中,而對(duì)象的元數(shù)據(jù)(類(lèi)型數(shù)據(jù))存儲(chǔ)在方法區(qū)。在我們進(jìn)行內(nèi)存優(yōu)化的過(guò)程中經(jīng)常需要了解每個(gè)對(duì)象占用的內(nèi)存大小。接下來(lái)我將介紹對(duì)象占用內(nèi)存大小的計(jì)算方式。
Java的對(duì)象模型
java是面向?qū)ο蟮恼Z(yǔ)言,每個(gè)對(duì)象都屬于某個(gè)類(lèi)。在HotSpot虛擬機(jī)中對(duì)象采用的是oop-klass模型。其實(shí)原理很簡(jiǎn)單:就是在方法區(qū)中生成一個(gè)Class類(lèi)保存類(lèi)信息(Klass),包含靜態(tài)常量、靜態(tài)方法、字節(jié)碼、即時(shí)編譯代碼等元數(shù)據(jù),而在堆中實(shí)例化該類(lèi)的實(shí)例對(duì)象(oop),實(shí)例對(duì)象中保存了指向Class類(lèi)的指針,這樣便構(gòu)成了oop-klass模型。這樣做有一個(gè)好處就是:在實(shí)現(xiàn)多態(tài)時(shí)只需要在Class類(lèi)中保存虛方法表來(lái)減少頻繁的方法搜索,而實(shí)例對(duì)象無(wú)需保存虛方法表。
每個(gè)對(duì)象都有一個(gè) mark work 頭部,以及一個(gè)引用(klass pointer)指向Class類(lèi)的信息。
java對(duì)象在內(nèi)存中模型如下:
Java對(duì)象內(nèi)存占用
對(duì)象大小分為:
如上圖例子所示:myClass 實(shí)例創(chuàng)建出來(lái)之后,在內(nèi)存中所占的大小就是 myClass 自身大小(Shadow heap size)。包括類(lèi)的頭部大小以及一個(gè)int的大小和一個(gè)引用的大小。myClass 中object 成員變量是一個(gè)對(duì)象引用,這個(gè)被引用的對(duì)象也占一定大小。myClass 實(shí)例所維護(hù)的引用的對(duì)象所占的大小,稱(chēng)為myClass實(shí)例的Retained heap size。我們這里僅討論如何計(jì)算對(duì)象自身的大小,引用對(duì)象大小的計(jì)算方式可依此類(lèi)推。
java對(duì)象內(nèi)存可分為:頭部 + 數(shù)據(jù) + 對(duì)齊字節(jié)
±-----------------±-----------------±----------------- ±--------------+
| mark word | klass pointer | data (opt) | padding |
±-----------------±-----------------±------------------±--------------+
(1)頭部大小(mark word + klass pointer)
(2)數(shù)據(jù)大小(data)
空對(duì)象不包含任何成員變量,其大小即對(duì)象頭大小。若存在成員成員,為了內(nèi)存緊湊,成員在內(nèi)存中的排列和聲明的順序可能不一致,這樣才能充分利用內(nèi)存空間。這是因?yàn)樵?2位系統(tǒng)中,對(duì)象大小需要為4byte(32位)的整數(shù)倍,而在64位的系統(tǒng)中,對(duì)象需要為8byte(64位)的整數(shù)倍。如下例子:
其內(nèi)存布局為:
值得一提的是,數(shù)組對(duì)象和普通對(duì)象存在一點(diǎn)小區(qū)別:數(shù)組多一個(gè)記錄數(shù)組長(zhǎng)度的 int 類(lèi)型(4byte)
總結(jié)
以上是生活随笔為你收集整理的JVM对象占用内存计算的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: IDEA常用快捷键【win-mac对比】
- 下一篇: cherry-pick的用法