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