jvm Java中变量的内存地址

6ju8rftf  于 2022-11-07  发布在  Java
关注(0)|答案(9)|浏览(290)

请看下面的图片。当我们在java中创建一个带有new关键字的对象时,我们从操作系统中获得了一个内存地址。
当我们写out.println(objName)时,我们可以看到一个“特殊”字符串作为输出。
1.这是什么输出?
1.如果是OS给我们的内存地址:
a)如何将此字符串转换为二进制?
B)如何获取一个整型变量的地址?

rsaldnfx

rsaldnfx1#

这是由'@'字符分隔的类名和System.identityHashCode()。标识散列代码所代表的是特定于实现的。它通常是对象的初始内存地址,但对象可以随着时间的推移在内存中移动。所以(简单地说)你不能依赖于它是任何东西。
获取变量的内存地址在Java中是没有意义的,因为JVM可以自由地实现对象并在合适的时候移动它们(在垃圾收集等过程中,对象可能/将移动)。
toBinaryString()将为您提供二进制形式的整数。

jpfvwuh4

jpfvwuh42#

可以使用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

结论:

  • 散列码!=地址
  • toString =类@十六进制(散列代码)
bq9c1y66

bq9c1y663#

这是Object的“toString()”实现的输出。如果你的类覆盖了toString(),它将打印出完全不同的内容。

wqnecbli

wqnecbli4#

这是不是内存地址这是类名@哈希码
Object.toString()的默认实现是什么?

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

其中
Class name =完全限定名或绝对名(即包名后接类名)hashcode =十六进制格式(System.identityHashCode(obj)或obj.hashCode()将以十进制格式为您提供散列代码)。
提示:
产生混淆的根本原因是Object.hashCode()的默认实现使用了将对象的内部地址转换为整数
这通常是通过将对象的内部地址转换为整数来实现的,但Java™编程语言并不需要这种实现技术。
当然,有些类可以覆盖toString()hashCode()的两种默认实现
如果您需要覆盖hashcode()的对象的默认实现值,
可以使用以下方法System.identityHashCode(Object x)

6rqinv9w

6rqinv9w5#

就像Sunil说的,这不是内存地址。这只是散列码
要获得相同的@内容,您可以:
如果在该类中未覆盖hashCode:

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

如果hashCode被覆盖,则使用以下语句获取原始值:

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

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

kcwpcxri

kcwpcxri6#

您得到的是Object类的toString()方法的结果,或者更准确地说,是uzay95指出的identityHashCode()的结果。
“当我们使用new关键字在java中创建一个对象时,我们将从操作系统中获取一个内存地址。”
在Java中所做的一切都是由Java虚拟机来处理的,这一点很重要。JVM提供了这些信息。主机操作系统的RAM中实际发生的情况完全取决于JRE的实现。

up9lanfz

up9lanfz8#

根据Javadoc的Printing对象引用,它将返回对象的字符串表示形式,因为它将在内部调用Object类的toString()方法。enter image description here

eufgjt7s

eufgjt7s9#

在Java中,当你从Person p = new Person();这样的类中创建一个对象时,p实际上是一个内存位置的地址,它指向Person类型。
当使用statemenet打印p时,您将看到一个地址。new关键字创建一个新的内存位置,其中包含所有包含在class Person中的示例变量和方法,p是指向该内存位置的引用变量。

相关问题