深入分析Java中打印对象内存地址 System.identityHashCode()方法

地址是什么样子的

我们知道system.out.println(new XXX())可以打印出内存地址
我们看个例子:

public class Test {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t);

看下输出的结果:

Test@139a55

toString()方法

这个结果是怎么来的呢,其实是调用了Test的toString()方法,该方法继承自Object

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

看到这里,toString方法其实是打印了对象自身的hashCode,Object的hashCode() 是一个native方法,默认返回的是内存地址。toString方法打印不是hashCode()返回的原值,而是经过转化的16进制字符

重写hashCode

我们知道,hashCode()可以重写,如果重写的话,同一个类型的2个实例,hashCode的值是相同的,但是地址肯定是不相同的,此时,如果想打印出地址怎么办?这时,不能直接调用hashCode了
我们再看个例子:

public class TestMem {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "world";
        String s3 = "helloworld";
        String s4 = s1+s2;
         System.out.println(s3.equals(s4));
        System.out.println(s3==s4);
        System.out.println(s3.hashCode());
        System.out.println(s4.hashCode());
        System.out.println(System.identityHashCode(s3));
        System.out.println(System.identityHashCode(s4));
 
    }
}

结果:

true         //字面值相同
false        //地址不同
-1524582912  //对比2个发现hashcode相同
-1524582912  
1284693
31168322

通过结果,我们发现s3和s4的字面值是相同的,但地址是不相同的,字面值相同是因为String类虽然继承了Object,但是重写了hashcode,地址不同可以通过identityHashCode打印出来

identityHashCode与真正的内存地址

严格来说,identityHashCode()并不指向真实的地址,关于对象的真正地址,可以参见 Java 正确获取对象内存地址的方式

要在 JVM 中查找对象的内存地址,需要 Java 对象布局 ( JOL ) 工具。

首先,添加 jol-core依赖:

<dependency> 
    <groupId>org.openjdk.jol</groupId>
    <artifactId>jol-core</artifactId>
    <version>0.10</version>
</dependency>

要在 JVM 中查找特定对象的内存地址,我们可以使用 addressOf() 方法:

String answer = "42";
System.out.println("The memory address is " + VM.current().addressOf(answer));

这将打印:

The memory address is 31864981224

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

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

参考

Java 正确获取对象内存地址的方式

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值