Java中对象的内存地址

2023/06/12

1. 概述

在这个快速教程中,我们将了解如何在Java中查找对象的内存地址。

在进一步讨论之前,值得一提的是,运行时数据区域的内存布局不是JVM规范的一部分,由实现者自行决定。因此,每个JVM实现可能有不同的策略来在内存中布局对象和数组。反过来,这将影响内存地址。

在本教程中,我们将重点介绍一个特定的JVM实现:HotSpot JVM。我们还会在整个教程中互换使用JVM和HotSpot JVM术语。

2. 依赖

要在JVM中查找对象的内存地址,我们将使用Java对象布局(JOL)工具。因此,我们需要添加jol-core依赖:

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

3. 内存地址

要在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不时移动对象而发生变化。

4. 身份哈希码

有一种常见的误解,认为JVM中对象的内存地址被表示为其默认toString实现的一部分,例如java.lang.Object@60addb54。也就是说,许多人认为“60addb54”是该特定对象的内存地址。

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

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: 31879960584
toString: java.lang.Object@60addb54
hashCode: 1622006612
hashCode: 1622006612

有趣的是,“60addb54”是哈希码的十六进制版本,即1622006612。hashCode()方法是所有Java对象的通用方法之一,当我们没有为类声明hashCode()方法时,Java将使用它的身份哈希码

如上所示,身份哈希码(toString中@后面的那部分)和内存地址是不同的

5. 总结

在这个简短的教程中,我们了解了如何在Java中查找对象的内存地址。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章