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

3.8k 技术 , 发表评论

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 是哈希码的十六进制版本,即1622006612hashCode()方法是所有 Java 对象的常用方法之一。当我们不为类声明 hashCode() 方法时,Java 将使用其身份哈希码 identityHashCode

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

原文地址:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

昵称 *