【问题标题】:Object header size in Java on 64bit VM with <4GB RAM在具有 <4GB RAM 的 64 位 VM 上 Java 中的对象标头大小
【发布时间】:2013-06-27 06:22:14
【问题描述】:

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

【问题讨论】:

    标签: java linux windows 64-bit


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

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

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

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

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

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

      【讨论】:

        【解决方案3】:

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

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

        【讨论】:

        • 当您参考@NitinS 答案时,您可以使用 cmets 而不是发布答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-08
        • 2020-08-27
        • 1970-01-01
        • 1970-01-01
        • 2011-10-18
        相关资源
        最近更新 更多