在<4GB RAM的64位虚拟机上Java中的对象头大小

我想知道是否有某种方法让64位虚拟机使用8字节对象头而不是12字节对象头,如果JVM的可用RAM是4GB的话。

还是这样在Linux上,如果不是在Windows上? 有人可以testing这个代码?

import java.lang.reflect.Field; import sun.misc.Unsafe; public class ObjectSizes { String s1; String s2; public static void main(String[] args) throws Exception { Unsafe unsafe; try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); unsafe = (Unsafe)field.get(null); } catch (Exception ex) { throw new RuntimeException("Can't get Unsafe instance.", ex); } Field s1Field = ObjectSizes.class.getDeclaredField("s1"); Field s2Field = ObjectSizes.class.getDeclaredField("s2"); long s1OffSet = unsafe.objectFieldOffset(s1Field); long s2OffSet = unsafe.objectFieldOffset(s2Field); System.out.println("We are running "+System.getProperty("java.version")); System.out.println("Object header size is "+s1OffSet+" bytes."); System.out.println("Object reference size is "+(s2OffSet-s1OffSet)+" bytes."); } } 

看起来在64位JVM上没有可能拥有一个8字节的对象头。 标题由一个“标记字”,一个指向对象类的指针,一个数组的情况下的数组大小和填充到达下一个8字节的边界组成。

  ,------------------+------------------+------------------ +---------------. | mark word | klass pointer | array size (opt) | padding | `------------------+------------------+-------------------+---------------' 
  • 标记字可用于存储原生指针以实现锁定并帮助GC ,因此它在64位JVM上占用8个字节。
  • 堆小于32GB时,指向对象类的指针被压缩为4个字节 。
  • 填充可以用来存储一个字段。

因此,64位系统上的对象头可以占用8 + 4 = 12个字节,但不能少于8个。

对于64位虚拟机有以下选项:

  1. 通过-XX使用压缩指针:+ UseCompressedOops(在Java 6上默认启用)

在这种情况下,对象头将是12个字节,数组头将是16个字节(数组大小的最后4个字节)

2.不通过-XX使用压缩指针:-UseCompressedOops

在这种情况下:对象标题将是16个字节,数组标题将是20个字节(数组大小的最后4个字节)

上面给出的代码不是VM大小独立的,并且对于32位和64位vms会给出不同的结果。 您需要考虑比特性和压缩oops因素来计算正确的大小。

通过-XX使用压缩指针:+ UseCompressedOops(在Java 6上默认启用)

对于所有版本的Java 6,这不是真的。- -XX:+UseCompressedOops默认情况下启用-XX:+UseCompressedOops ,从Java 6u25开始