java查看对象真实地址和哈希值的工具类

System.identityHashCode()可以查看对象未被重写的hashcode值;
VM.current().addressOf()在JVM中查找特定对象的内存地址;
有一种常见的误解,认为 JVM 中对象的内存地址是作为其默认 toString 实现的一部分表示的,例如 java.lang.Object@1b4fb997

也就是说,许多人认为这里的 1b4fb997是该特定对象的内存地址。

让我们检查一下这个假设:

Object obj = new Object();

System.out.println("Memory address: " + VM.current().addressOf(obj));
System.out.println("toString: " + obj);
System.out.println("hashCode: " + obj.hashCode());
System.out.println("hashCode: " + System.identityHashCode(obj));

输出内容:
Memory address: 31879919208
toString: java.lang.Object@1b4fb997
hashCode: 458209687
hashCode: 458209687

有趣的是, 1b4fb997 哈希码的十六进制版本,即458209687。hashCode()方法是所有 Java 对象的常用方法之一。当我们不为类声明 hashCode() 方法时,Java 将使用其身份哈希码 identityHashCode

如上所示,标识哈希码(toString中输出的后半部分)和存储器地址是不同的。


注意:

HotSpot JVM 中有不同的压缩引用模式。由于这些模式,此值可能不完全准确。因此,我们不应该根据该地址执行一些本机内存操作,因为它可能会导致奇怪的内存损坏。

此外,大多数 JVM 实现中的内存地址会随着 GC 不时移动对象而发生变化。


测试

pom.xml

        <dependency>
            <groupId>org.openjdk.jol</groupId>
            <artifactId>jol-core</artifactId>
            <version>0.16</version>
        </dependency>
public class TestMemory {

    public static void main(String[] args) {
        String s = new String("你好".getBytes(StandardCharsets.UTF_8));
        System.out.println("String类型hash值:"+s.hashCode());
        System.out.println("String类型hash值:"+System.identityHashCode(s));
        System.out.println("String类型地址值:"+VM.current().addressOf(s));
        s = "xxx";
        System.out.println("String类型修改后hash值:"+s.hashCode());
        System.out.println("String类型修改后hash值:"+System.identityHashCode(s));
        System.out.println("String类型修改后地址值:"+VM.current().addressOf(s));

        Person person = new Person();
        System.out.println("对象类型hash值:"+person.hashCode());
        System.out.println("对象类型hash值:"+System.identityHashCode(person));
        System.out.println("对象类型地址值:"+person);
        System.out.println("对象类型地址值:"+VM.current().addressOf(person));
        person.age = 2;
        System.out.println("对象类型修改后hash值:"+person.hashCode());
        System.out.println("对象类型修改后hash值:"+System.identityHashCode(person));
        System.out.println("对象类型修改后地址值:"+person);
        System.out.println("对象类型修改后地址值:"+VM.current().addressOf(person));
    }

    static  class  Person{
        int age;
    }
}

在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

L-960

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值