java一個對象多大?


  最近在看點不知道什么鬼的東西,看得到了一個讓我眼前一亮的新東西,感覺很有趣,記錄一下;

  我們怎么知道一個java對象的大小呢?比如HashMap<String,Object> map = new HashMap<>();,這個map對象在堆中多大呢?占多少個字節呢?

  我們可以借助apache的一個類RamUsageEstimator來計算,例如下面這種:

<dependency>
   <groupId>org.apache.lucene</groupId>
   <artifactId>lucene-core</artifactId>
   <version>6.6.1</version>
 </dependency>

Integer integer
= new Integer(10); HashMap<String,Object> map = new HashMap<>();
System.out.println(RamUsageEstimator.shallowSizeOf(integer));
//16 System.out.println(RamUsageEstimator.shallowSizeOf(map)); //48

 

   我們可以看到最后計算出來的一個Integer是16個字節,一個HashMap是48個字節;

  這個時候肯定會有人說,(#`㉨´)凸不對呀,不是說int類型是4個字節的嗎?為什么包裝類型Integer的就是16個字節了呢?

  要知道這個問題,首先我們要知道在java堆中實例化的對象是由什么構成的?前面博客說了的,這里簡單的提一下,分三部分:對象頭,實例數據,對齊填充

 

  主要說一下對象頭,對象頭由兩部分組成,64位jvm中markword占8個字節(一般都是64位的吧,32位的虛擬機就占4個字節),第二部分是klass類型的指針占4個字節!如果是數組,那么此處還有第三部分,數組長度占4個字節;

  然后上面例子中Integer的對象頭應該是8+4=12,然后實例數據我們需要看Integer類以及父類中有幾個實例變量,只有一個,下圖所示(注意,是實例變量,不能是native和static修飾的),如果是引用類型就占4個字節用於記錄地址;int類型4個字節,於是12+4=16,剛好是8的倍數,無需對齊填充;

 

  我們再說說那么HashMap,對象頭也是12,實例數據,我們要看看HashMap的父類有兩個屬性,是引用類型,每一個占4個字節;

 

  再看看HashMap本類中有幾個屬性,可以看到6個,共占24個字節

 
transient Node<K,V>[] table;//引用類型,占四個字節

transient Set<Map.Entry<K,V>> entrySet;//引用類型,占四個字節

transient int size;//int類型,4個字節

transient int modCount;//int類型,4個字節

int threshold;//int類型,4個字節

final float loadFactor;//int類型,4個字節

 

   所以就是12+4+4+24=44,由於java對象占的字節數必須要是8的倍數,所以對齊填充,在最后補4個字節,所以總共就是48個字節,很容易吧!

  另外,想深入了解一下的java對象的組成,可以參考這篇博客,說的還是很詳細的:https://blog.csdn.net/haihui_yang/article/details/81071693


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM