为什么在JVM中交换对象位置?

Arp*_*ari 6 java

这是我试过的:

public final class firstObj{    
    public static void main(String args[]){    
        Object obj = new Object();    
        Object obj1 = new Object();    
        System.out.println(obj);
        System.out.println(obj1);    
    }    
}
Run Code Online (Sandbox Code Playgroud)

我首先编译了程序并连续运行了两次,我得到了两个不同的输出:

输出1:

java.lang.Object@6f548414
java.lang.Object@65ab7626
Run Code Online (Sandbox Code Playgroud)

输出2:

java.lang.Object@659c2931
java.lang.Object@6f548414
Run Code Online (Sandbox Code Playgroud)

我想知道为什么JVM将第二个对象的位置交换到第一个对象的位置当它第二次运行时...,这是非常令人困惑的......

Pet*_*rey 2

hashCode() 与内存中的位置关系不大。虽然它看起来像一个地址,但它只是一个随机生成的数字。

我并不期望它总是从同一个段分配,但我想知道对象是否是连续分配的,因为我的输出显示了一些这样的模式

这是预料之中的,因为它是一个随机数。


如果您在 OpenJDK 或 Oracle 热点上运行它,您就会得到。

import sun.misc.Unsafe;

import java.lang.reflect.Field;

public class ObjectAddress {
    public static void main(String[] args) {
        Object o1 = new Object();
        Object o2 = new Object();
        Object o3 = new Object();
        Object[] os = {o1, o2, o3};
        System.out.println("Before using hashCode");
        for (int i = 0; i < os.length; i++) {
            int address = UNSAFE.getInt(os, UNSAFE.arrayBaseOffset(Object[].class) + i * 4);
            int hashCode = UNSAFE.getInt(os[i], 1L);
            System.out.println(i + ": " + Integer.toHexString(address) + " hashCode " + Integer.toHexString(hashCode));
            os[i].hashCode();
        }
        System.out.println("After using hashCode");
        for (int i = 0; i < os.length; i++) {
            int address = UNSAFE.getInt(os, UNSAFE.arrayBaseOffset(Object[].class) + i * 4);
            int hashCode = UNSAFE.getInt(os[i], 1L);
            System.out.println(i + ": " + Integer.toHexString(address) + " hashCode " + Integer.toHexString(hashCode) + " for " + os[i]);
            UNSAFE.putInt(os[i], 1L, 0x12345678);
        }
        System.out.println("After setting the hashCode");
        for (int i = 0; i < os.length; i++) {
            int address = UNSAFE.getInt(os, UNSAFE.arrayBaseOffset(Object[].class) + i * 4);
            int hashCode = UNSAFE.getInt(os[i], 1L);
            System.out.println(i + ": " + Integer.toHexString(address) + " hashCode " + Integer.toHexString(hashCode) + " for " + os[i]);
            os[i].hashCode();
        }

    }

    static final Unsafe UNSAFE;

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);
            UNSAFE = (Unsafe) theUnsafe.get(null);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

你会得到类似的东西

Before using hashCode
0: d8e78160 hashCode 0
1: d8e78170 hashCode 0
2: d8e78180 hashCode 0
After using hashCode
0: d8e78160 hashCode 68111f9b for java.lang.Object@68111f9b
1: d8e78170 hashCode 3c322e7d for java.lang.Object@3c322e7d
2: d8e78180 hashCode 3e2f1b1a for java.lang.Object@3e2f1b1a
After setting the hashCode
0: d8e78160 hashCode 12345678 for java.lang.Object@12345678
1: d8e78170 hashCode 12345678 for java.lang.Object@12345678
2: d8e78180 hashCode 12345678 for java.lang.Object@12345678
Run Code Online (Sandbox Code Playgroud)

可以看到每个Object相隔16个字节。

  • 内存中的位置可能会对哈希码值产生影响“这通常是通过将对象的内部地址转换为整数来实现的,但 Java™ 编程语言不需要这种实现技术。” 来自 [`hashcode()`](http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()) (2认同)