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

posted @ 2020-03-25 15:11  java小新人  阅读(1559)  评论(2编辑  收藏  举报