目前,我正在使用Eclipse内存分析器插件(使用标准的jconsole hprof转储)分析一些Java应用程序,并注意到计算对象大小的一些奇怪结果:
private static class B1 extends B {
} // 16 bytes
private static class B2 extends B {
boolean d1;
boolean d2;
boolean d3;
boolean d4;
} // also 16 bytes!
private static class B3 extends B {
boolean d1;
boolean d2;
boolean d3;
boolean d4;
boolean d5;
} // 24 bytes显然前4个布尔人被塞进了对象头中,这是怎么回事?
注意:使用OracleJDK1.7和JDK1.8测试64位,运行在Linux x64上。
发布于 2014-09-12 14:37:46
在64位HotSpot JVM内使用CompressedOops。
markWord +4字节instanceKlass引用组成。boolean字段占用1字节那是
align8(8 + 4) = 16 bytesalign8(8 + 4 + 4*1) = 16 bytesalign8(8 + 4 + 5*1) = align8(17) = 24 bytes发布于 2014-09-12 14:33:20
没有进行优化;对象头通常是8或12个字节,这取决于VM和模式(压缩的OOPS打开/关闭)。此外,内存粒度通常为8字节(内存中的对象大小必须是粒度的倍数)。
您的结果清楚地表明,您的VM使用了一个12字节的头;因此,由于粒度的原因,可以容纳4个字节,而不会增加内存占用。布尔值通常表示为字节;因此,在您的示例中添加第五个字节需要17个字节(12个头+5个字节)四舍五入到下一个粒度,8边界为24个字节。
发布于 2014-09-12 14:41:08
我没看到你是什么。使用1.8,来自Netbeans:
public static class C1 {
boolean a,b,c,d;
}
public static class C2 {
boolean a,b,c,d,e;
}
public static void main(String[] args) {
try {
Constructor<Unsafe> unsafeConstructor = Unsafe.class.getDeclaredConstructor();
unsafeConstructor.setAccessible(true);
Unsafe unsafe = unsafeConstructor.newInstance();
String[] fieldNames = new String[] {"a","b","c","d"};
for (String fieldName : fieldNames) {
System.out.println(fieldName+": "+unsafe.objectFieldOffset(C1.class.getDeclaredField(fieldName)));
}
}
catch(Exception e) {
e.printStackTrace();
}
}产生结果
a: 12
b: 13
c: 14
d: 15...which表示每个布尔值在对象中占据单独的字节偏移量。标头为12个字节。
https://stackoverflow.com/questions/25810548
复制相似问题