在Java对象头部大小在64位虚拟机以< 4GB内存头部、虚拟机、大小、对象

2023-09-08 00:53:26 作者:冷月醉夕阳

我想知道是否有一些方法来有64位虚拟机使用8个字节对象头,而不是12byte对象的头文件,如果可用内存为JVM是4GB的反正。

或者是像在Linux上,如果无法在Windows?可能有人与此code测试呢?

 进口java.lang.reflect.Field中;
进口sun.misc.Unsafe;
公共类ObjectSizes {
    字符串S1;
    字符串s2;
    公共静态无效的主要(字串[] args)抛出异常{
        不安全不安全;
        尝试 {
            场场= Unsafe.class.getDeclaredField(theUnsafe);
            field.setAccessible(真正的);
            不安全=(不安全)field.get(空);
        }赶上(例外前){
            抛出新的RuntimeException(无法获取不安全的实例。前);
        }
        现场s1Field = ObjectSizes.class.getDeclaredField(S1);
        字段s2Field = ObjectSizes.class.getDeclaredField(S2);
        长s1OffSet = unsafe.objectFieldOffset(s1Field);
        长s2OffSet = unsafe.objectFieldOffset(s2Field);
        的System.out.println(我们正在运行的+ System.getProperty(java.version));
        的System.out.println(对象头部大小为+ s1OffSet +字节);
        的System.out.println(对象大小+(s2OffSet-s1OffSet)+字节);
    }
}
 

解决方案

它看起来并不像它可能有一个64位JVM 8个字节的对象标题。首标包括一个标记字,一个指向该对象的类,在壳体的阵列的阵列大小,和填充到到达下一个8字节边界

 ,------------------ + ------------------ + ------------------ + ---------------。
  |标志字|克拉斯指针|数组大小(OPT)|填充|
  `------------------ + ------------------ + ----------- -------- + ---------------
 

标记词可以用来存储本机的指针实行锁并帮助GC ,所以它占用8个​​字节在64位JVM。 随着堆比32GB的小指针指向对象的类为com pressed到4个字节。 的填充可以用于存储的领域之一。

因此​​在64位的系统中的对象首标可以少占8 + 4 = 12字节,但不小于

如何查看一个 Java 对象的大小

I wanted to know if there is some way to have the 64bit VM use 8byte object headers instead of 12byte object headers if the usable RAM for the JVM is 4GB anyway.

Or is it like that on Linux, if not on windows? Could someone test this with this code?

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

解决方案

It doesn't look like it's possible to have an 8-byte object header on a 64-bit JVM. The header consists of a "mark word", a pointer to the object's class, array size in case of an array, and padding to reach the next 8-byte boundary.

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

The mark word may be used to store native pointers to implement locks and to help GC, so it occupies 8 bytes on a 64-bit JVM. With heaps smaller than 32GB the pointer to the object's class is compressed to 4 bytes. The padding may be used to store one of the fields.

Therefore the object header on a 64-bit system can occupy as little as 8 + 4 = 12 bytes, but not less.

 
精彩推荐