• 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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

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

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


    注意:

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

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


    测试

    pom.xml

            <dependency>
                <groupId>org.openjdk.jolgroupId>
                <artifactId>jol-coreartifactId>
                <version>0.16version>
            dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    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;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

  • 相关阅读:
    【Linux】生产者消费者模型
    打造“共富果园” 广东乳源推动茶油全产业链高质量发展
    4、FFmpeg命令行操作7
    服务器有几种http强制跳转https设置方法
    电容笔什么牌子好?比较好用的ipad手写笔推荐
    SpringBoot中使用Apache Kafka客户端
    15经验模态分解及其改进程序,EMD,EEMD, CEEMDAN,三合一程序,已调试完成,替换自己数据可直接跑。
    时间复杂度为 O(n^2) 的排序算法
    MySql学习之慢SQL优化和慢SQL案例
    Azure DevOps Server 设置项目管理用户,用户组
  • 原文地址:https://blog.csdn.net/weixin_43702146/article/details/126638899