Java中变量的内存地址

uza*_*y95 128 java jvm memory-management hashcode memory-address

请看下面的图片.当我们用java创建一个带有new关键字的对象时,我们从OS获取一个内存地址.

当我们写作时,new我们可以看到一个"特殊"字符串作为输出.我的问题是:

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

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

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

替代文字

Bri*_*new 153

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

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

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

  • 另一个有趣的观点是*身份哈希码*不保证是唯一的.例如,在64位JVM上,有2 ^ 32个身份*哈希码*但是2 ^ 64*内存地址*. (32认同)
  • 实际上,身份哈希码[不能改变](http://stackoverflow.com/questions/3796699/will-hashcode-return-different-int-due-to-cmpaction-of-tenure-space),否则合同hashCode()将被违反. (9认同)
  • 我使用它进行日志记录/调试,以确定日志中的对象何时指向同一对象而不是等效对象。出于这些目的,“identityHashcode”并非毫无意义,只是并非万无一失。:) (3认同)

JBE*_*JBE 33

有可能使用sun.misc.Unsafe:从@Peter Lawrey看到这个很好的答案 - > 有没有办法获得参考地址?

使用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();
}
Run Code Online (Sandbox Code Playgroud)

我设置了这个测试:

    //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);
Run Code Online (Sandbox Code Playgroud)

这是输出:

Hashcode :       125665513
Hashcode :       125665513
Hashcode (HEX) : 77d80e9
toString :       java.lang.Object@77d80e9
Address: 0x7aae62270
Run Code Online (Sandbox Code Playgroud)

结论:

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


Pau*_*lin 11

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


Top*_*era 7

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

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

如果该类中未覆盖 hashCode:

"@" + Integer.toHexString(obj.hashCode())
Run Code Online (Sandbox Code Playgroud)

如果 hashCode 被覆盖,您将获得原始值:

"@" + Integer.toHexString(System.identityHashCode(obj)) 
Run Code Online (Sandbox Code Playgroud)

这经常与内存地址混淆,因为如果您不覆盖 hashCode(),内存地址将用于计算散列。


Sun*_*hoo 6

不是内存地址 这是classname @ hashcode

哪里

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

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