Java 正确获取对象内存地址的方式
1. 概述
在本教程中,我们将了解如何在 Java 中查找对象的内存地址。
在此之前,我们需要说明的是,运行时数据区的内存布局不是 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. 错误的方式:identityHashCode()
有一种常见的误解,认为 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 将使用其身份哈希码 identityHashCode
。
如上所示,标识哈希码(toString
中输出的后半部分)和存储器地址是不同的。
原文地址: