根据 Memory usage of Java objects: general guide :
在热点中:
a normal object requires 8 bytes of "housekeeping" space;
arrays require 12 bytes (the same as a normal object, plus 4 bytes for the array length).
对象大小粒度
In Hotspot, every object occupies a number of bytes that is a multiple of 8. If the number of bytes required by an object for its header and fields is not a multiple 8, then you round up to the next multiple of 8.
This means, for example, that:
- 一个裸对象占用8个字节;
- 具有单个 boolean 字段的类的实例占用 16 个字节:8 个字节的 header ,1 个字节的 boolean 值和 7 个字节的“填充”,使大小达到 8 的倍数;
- 具有八个 boolean 字段的实例也将占用 16 个字节:
- 8 个用于 header ,8 个用于 boolean 值;因为这已经是 8 的倍数,所以不需要填充;
- 具有两个 long 字段、三个 int 字段和一个 boolean 值的对象将占用:
- 8 个字节用于 header ;
- 2 个 long 为 16 个字节(每个 8 个);
- 3 个整数(每个 4 个)12 个字节;
- 1 个字节用于 boolean 值;
- 另外 3 个字节的填充,将总数从 37 向上取整到 40,即 8 的倍数。
我的问题:
裸 java.lang.Object 没有字段。所以 new Ojbect()
将占用堆中的 8 个字节。
但是当我使用 instrumentation agent 测试 new Object()
的大小时实用程序。
System.out.println(MemoryUtil.deepMemoryUsageOf(new Object()));
结果是 16
,而不是 8
。谁能告诉我为什么?
编辑:
据我所知,the object header在 x86 上,它的大小是 4 字节。
而且对象 header 包含同步的锁定信息。
// 32 bits:
// --------
// hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
// JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
// size:32 ------------------------------------------>| (CMS free block)
// PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
所以一个对象的开销是 4byte(对象头)+ 4byte(类指针)= 8byte。
最佳答案
这interesting presentation可能会给您额外的见解。
基本上,由于内存对齐和填充在 64 位 JVM 中为 8 个字节,因此对象开销为 16 个字节:每个属性( header 和类引用)占用 8 个字节。请参阅演示文稿中的幻灯片 38。但是请注意,当使用 JVM 选项 -XX:+UseCompressedOops
时,开销减少到 12 个字节。
关于java - JVM 中裸 java.lang.Object 的实际大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21397125/