Do Objects Move in Memory During JVM Garbage Collection? Handles vs Direct Pointers Explained
This article explores how the JVM updates object references during garbage collection, compares handle‑based and direct‑pointer implementations, demonstrates why the default toString output shows a hashcode rather than a real address, and shows how to obtain the actual memory address using the JOL library.
Preface
A recent technical discussion with a friend raised the question of whether an object's address changes when the JVM moves it during garbage collection, prompting a deeper investigation into JVM reference handling.
Updating References Is the JVM's Responsibility
Regardless of the garbage‑collection algorithm, the JVM must update all references to a moved object; this work is handled entirely by the JVM, abstracting the details away from developers.
Handle Access
In the handle‑based model, the heap maintains a handle pool; object references store the handle's location, while the handle contains the actual object address. This makes the reference stable because only the handle pool needs updating when objects move.
Advantages: reference stability and reduced update cost when multiple variables point to the same handle. Disadvantage: an extra level of indirection can affect access speed.
Direct Pointer Access
The direct‑pointer model stores the actual object address in the reference, eliminating the handle pool.
Advantages: faster access because no extra indirection. Disadvantage: when the GC moves an object, every reference holding the address must be updated, which can be costly if many variables point to the same object. HotSpot uses this approach.
How to Inspect an Object’s Address
Printing an object with System.out.println(object) invokes Object.toString(), which concatenates the class name with the hexadecimal representation of the object's hashcode, not its memory address.
Bike bike = new Bike();
System.out.println(bike);Typical output:
com.secbro2.others.Bike@4dc63996The part after "@" is the hashcode in hex, not a real address.
To obtain the actual memory address, the Java Object Layout (JOL) library can be used. Add the following Maven dependency:
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>Then call:
String answer = "42";
System.out.println("The memory address is " + VM.current().addressOf(answer));Sample output:
The memory address is 31856221536Note that the printed address may vary due to pointer‑compression techniques used by different JVMs, so it should not be relied upon for portable native‑memory operations. The toString hashcode can only guarantee equality of hashcodes, not that two references point to the same physical address.
Conclusion
The JVM automatically updates object references during GC, with the exact behavior depending on whether the VM uses a handle pool or direct pointers. The default toString output shows a hashcode, not the actual memory address; obtaining a real address requires tools like JOL, but such addresses are JVM‑specific and not suitable for cross‑environment code.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Senior Brother's Insights
A public account focused on workplace, career growth, team management, and self-improvement. The author is the writer of books including 'SpringBoot Technology Insider' and 'Drools 8 Rule Engine: Core Technology and Practice'.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
