Java中变量的内存地址

时间:2009-12-25 13:10:42

标签: java memory-management jvm hashcode memory-address

请看下面的图片。 当我们使用new关键字在java中创建对象时,我们从操作系统获取内存地址。

当我们写out.println(objName)时,我们可以看到一个“特殊”字符串作为输出。我的问题是:

  1. 这是什么输出?
  2. 如果是操作系统给我们的内存地址:

    a)如何将此字符串转换为二进制文件?

    b)如何获得一个整数变量地址?

  3. alt text

8 个答案:

答案 0 :(得分:143)

这是由“@”字符分隔的类名和System.identityHashCode()。标识哈希码表示的是特定于实现的。它通常是对象的初始内存地址,但是VM可以随着时间的推移将对象移动到内存中。所以(简单地说)你不能依赖它是什么。

在Java中获取变量的内存地址是没有意义的,因为JVM可以自由地实现对象并在它们看起来合适时移动它们(您的对象可能/将在垃圾收集等过程中移动)。

Integer.toBinaryString()将为您提供二进制形式的整数。

答案 1 :(得分:27)

可以使用sun.misc.Unsafe:从@Peter Lawrey看到这个很棒的答案 - > Is there a way to get a reference address?

将其代码用于printAddresses():

    public static void printAddresses(String label, Object... objects) {
    System.out.print(label + ": 0x");
    long last = 0;
    int offset = unsafe.arrayBaseOffset(objects.getClass());
    int scale = unsafe.arrayIndexScale(objects.getClass());
    switch (scale) {
    case 4:
        long factor = is64bit ? 8 : 1;
        final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor;
        System.out.print(Long.toHexString(i1));
        last = i1;
        for (int i = 1; i < objects.length; i++) {
            final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor;
            if (i2 > last)
                System.out.print(", +" + Long.toHexString(i2 - last));
            else
                System.out.print(", -" + Long.toHexString( last - i2));
            last = i2;
        }
        break;
    case 8:
        throw new AssertionError("Not supported");
    }
    System.out.println();
}

我设置了这个测试:

    //hashcode
    System.out.println("Hashcode :       "+myObject.hashCode());
    System.out.println("Hashcode :       "+System.identityHashCode(myObject));
    System.out.println("Hashcode (HEX) : "+Integer.toHexString(myObject.hashCode()));

    //toString
    System.out.println("toString :       "+String.valueOf(myObject));

    printAddresses("Address", myObject);

这是输出:

Hashcode :       125665513
Hashcode :       125665513
Hashcode (HEX) : 77d80e9
toString :       java.lang.Object@77d80e9
Address: 0x7aae62270

结论:

  • hashcode!=地址
  • toString = class @ HEX(hashcode)

答案 2 :(得分:11)

这是Object的“toString()”实现的输出。如果你的类重写toString(),它将打印完全不同的东西。

答案 3 :(得分:5)

这是非内存地址 这是 classname @ hashcode

其中

classname =完全限定名称或绝对名称(即包名称后跟类名称)

hashcode =十六进制格式(System.identityHashCode(obj)或obj.hashCode()将为您提供十进制格式的哈希码)

答案 4 :(得分:2)

就像Sunil所说,这不是内存地址。这只是哈希码

要获得相同的@内容,您可以:

如果在该类中未覆盖hashCode:

"@" + Integer.toHexString(obj.hashCode())

如果重写了hashCode,则会获得原始值:

"@" + Integer.toHexString(System.identityHashCode(obj)) 

这常常与内存地址混淆,因为如果不覆盖hashCode(),则使用内存地址来计算哈希值。

答案 5 :(得分:1)

你得到的是Object类的toString()方法的结果,或者更准确地说,是uzay95指出的identityHashCode()的结果。

“当我们使用new关键字在java中创建一个对象时,我们从操作系统获取一个内存地址。”

重要的是要意识到您在Java中所做的一切都由Java虚拟机处理。它是提供此信息的JVM。在主机操作系统的RAM中实际发生的事情完全取决于JRE的实现。

答案 6 :(得分:1)

在Java中,当您从类Person p = new Person();这样的类创建对象时,p实际上是指向Person类型的内存位置的地址。

使用statemenet打印p时,您会看到一个地址。 new关键字使包含class Personp中包含的所有实例变量和方法的新内存位置成为指向该内存位置的引用变量。

答案 7 :(得分:0)