10

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

或者如果不是在 Windows 上,在 Linux 上也是这样吗?有人可以用这段代码测试吗?

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.");
    }
}
4

3 回答 3

17

看起来在 64 位 JVM 上不可能有 8 字节的对象标头。标头包含一个“标记字”、一个指向对象类的指针、数组大小(如果是数组)以及到达下一个 8 字节边界的填充。

  ,------------------+------------------+------------------ +---------------.
  |    mark word     |   klass pointer  |  array size (opt) |    padding    |
  `------------------+------------------+-------------------+---------------'

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

于 2013-06-27T16:24:46.237 回答
3

对于 64 位 VM,有以下选项:

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

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

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

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

上面给出的代码与 VM 位大小无关,对于 32 位和 64 位 vm 会给出不同的结果。您需要考虑位数和压缩 oops 因素来计算正确的大小。

于 2014-01-26T08:31:45.983 回答
-1

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

这不适用于所有版本的 Java 6。-XX:+UseCompressedOops从 Java 6u25 开始默认启用

于 2015-02-11T16:09:58.800 回答