1. Overview
1.概述
In this quick tutorial, we’re going to see how to find the memory address of objects in Java.
在这个快速教程中,我们将看到如何在Java中找到对象的内存地址。
Before going any further, it’s worth mentioning that the memory layout of runtime data areas is not part of the JVM specification and is left to the discretion of the implementor. Therefore, each JVM implementation may have a different strategy to layout objects and arrays in memory. This will, in turn, affect the memory addresses.
在进一步讨论之前,值得一提的是,运行时数据区域的内存布局并不是JVM规范的一部分,而是由实现者自行决定的。因此,每个 JVM 实现都可能有不同的策略来布局内存中的对象和数组。这将反过来影响内存地址。
In this tutorial, we’re focusing on one specific JVM implementation: the HotSpot JVM. We also may use the JVM and HotSpot JVM terms interchangeably throughout the tutorial.
在本教程中,我们将专注于一个特定的JVM实现:HotSpot JVM。在整个教程中,我们也可能交替使用JVM和HotSpot JVM的术语。
2. Dependency
2.依赖性
To find the memory address of objects in the JVM, we’re going to use the Java Object Layout (JOL) tool. Therefore, we need to add the jol-core dependency:
为了找到JVM中对象的内存地址,我们要使用Java Object Layout(JOL)工具。因此,我们需要添加jol-core依赖项。
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
3. Memory Address
3.内存地址
To find the memory address of a particular object in the JVM, we can use the addressOf() method:
为了找到JVM中一个特定对象的内存地址,我们可以使用addressOf()方法。
String answer = "42";
System.out.println("The memory address is " + VM.current().addressOf(answer));
This will print:
这将打印。
The memory address is 31864981224
There are different compressed reference modes in the HotSpot JVM. Because of these modes, this value may not be completely accurate. Therefore, we shouldn’t go and perform some native memory manipulations based on this address, as it may cause weird memory corruptions.
在HotSpot JVM中有不同的压缩参考模式。由于这些模式的存在,这个值可能不完全准确。因此,我们不应该去根据这个地址执行一些本地内存操作,因为这可能会导致奇怪的内存损坏。
Also, memory addresses in most JVM implementations are subject to change as the GC moves the objects around from time to time.
另外,在大多数JVM实现中,内存地址会随着GC不时地移动对象而发生变化。
4. Identity Hash Code
4.身份哈希代码
There’s a common misconception that the memory addresses of objects in the JVM are represented as part of their default toString implementations, such as java.lang.Object@60addb54. That is, many think that the “60addb54” is the memory address of that particular object.
有一个常见的误解,即JVM中的对象的内存地址被表示为其默认的toString 实现的一部分,例如java.lang.Object@60addb54。也就是说,许多人认为“60addb54”是该特定对象的内存地址。
Let’s check this assumption:
让我们检查一下这个假设。
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));
This will print the following:
这将打印出以下内容。
Memory address: 31879960584
toString: java.lang.Object@60addb54
hashCode: 1622006612
hashCode: 1622006612
Quite interestingly, the “60addb54” is the hexadecimal version of the hash code, which is 1622006612. The hashCode() method is one of the common methods for all Java objects. When we don’t declare a hashCode() method for a class, Java will use the identity hash code for it.
相当有趣的是,“60addb54”是哈希代码的十六进制版本,即1622006612。hashCode()方法是所有Java对象的通用方法之一。当我们没有为一个类声明hashCode()方法时,Java将为其使用身份哈希代码。
As shown above, the identity hash code (that part after @ in toString) and the memory address are different.
如上所示,身份哈希代码(toString中@之后的部分)和内存地址是不同的。
5. Conclusion
5.总结
In this short tutorial, we saw how to find the memory address of objects in Java.
在这个简短的教程中,我们看到了如何在Java中找到对象的内存地址。
As usual, all the examples are available over on GitHub.
像往常一样,所有的例子都可以在GitHub上找到。