一个对象的引用占多少个字节呢?4个?8个?算出来都不对

finallygo 2013-09-16
我有一个对象大概是这个样子的

public class Test {
  private long id;
  private Test2 test2;
  private List<Test3> list;
  private Date date;
  private byte status;
  private byte count;
}


我通过jmap算出来一个对象占用的内存大小是40个字节,但是我自己算发现,不管是用4个字节算(8+8+4+4+4+1+1=30)还是8个字节算(8+8+8+8+8+1+1=42)得出来的结果 都不是40,求解答呀


另外说下,我的jvm 信息如下:
java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)
RednaxelaFX 2013-09-16
JDK6u23后在64位VM上会默认开压缩指针,所以下面以开了压缩指针为前提来讨论。

public class Test {
  private long id;
  private Test2 test2;
  private List<Test3> list;
  private Date date;
  private byte status;
  private byte count;
}

加载时字段被重排序为:
// 1. long/double
// 2. int/float
// 3. short/char
// 4. byte/boolean
// 5. Object
public class Test {         // 8 (_mark) + 4 (_metadata._compressed_klass)
  private byte status;      // 1
  private byte count;       // 1
                            // padding: 2
  private long id;          // 8
  private Test2 test2;      // 4
  private List<Test3> list; // 4
  private Date date;        // 4
                            // padding: 4
}

就这样嗯,正好40。
finallygo 2013-09-16
1.我使用 你写的 CheckCompressedOopsMode.java 测试了下,返回 "Using compressed oops: true" ,然后我看下压缩的模式, 因为我配置的是jvm 参数是"-Xmx4096m -Xms4096m ",那使用的模式是 "zero based Compressed Oops" 吧?? 我想问问,使用 "zero based Compressed Oops, 32-bits Oops" 这种模式是不是效率更好一些呢??

2.我想问问重排序的规则是怎么样的?为什么不把 status,count,date 这三个放一起呢? 这样是不是又少了一个字节?

RednaxelaFX 2013-09-16
finallygo 写道
1.我使用 你写的 CheckCompressedOopsMode.java 测试了下,返回 "Using compressed oops: true" ,然后我看下压缩的模式, 因为我配置的是jvm 参数是"-Xmx4096m -Xms4096m ",那使用的模式是 "zero based Compressed Oops" 吧?? 我想问问,使用 "zero based Compressed Oops, 32-bits Oops" 这种模式是不是效率更好一些呢??

4G的Java heap意味着GC heap整体比4G大(一直到JDK7还有PermGen,这也是GC heap的一部分),所以是的,这里的压缩指针模式是带0基地址、带3位位移的模式。当然,如果不带位移的话更快一些,但如果您就需要那么大的堆的话那也没办法。

finallygo 写道
2.我想问问重排序的规则是怎么样的?为什么不把 status,count,date 这三个放一起呢? 这样是不是又少了一个字节?

规则是默认条件下把字段按宽度重排序,越宽的在越前面,例外是把所有引用类型字段放到最后。所以这里是long/double在最前,其它我在前面回帖的注释里已经写了。

开压缩指针模式的时候,对象头是12字节的,而long/double字段要从8字节对齐的偏移量开始(也就是至少要从+16的地方开始),这样中间就有一个4字节的缝(gap)。HotSpot会试图先从后面找一个4字节的字段补上来,没有的话找2字节的字段,再没有就找1字节的字段,最好还没有会找引用类型字段。上面例子里没有int、short但是有byte字段,那俩byte字段就被提升到前面放进gap里了。

status, count和date放一起为啥会省字节?
finallygo 2013-09-16
哦...是这样啊,谢谢了
1.堆大小我可以调整的,如果能提高速度的话,那我就把堆大小设置小一些了,只要保证 新生代 + 老生代 + 持久代 的大小小于4G,就行了吧?

2.我之前没有考虑到需要补足8个字节的问题,所以以为可以节省一些,不过为啥要补齐8个字节呢??为了解析的时候方便?
Global site tag (gtag.js) - Google Analytics