While that’s one way to do it, I believe that current JVMs use an index directly to the target object in the Java heap. Since the garbage collector is following all the references anyway, it can eventually update all the old references to point directly to an object after moving it.
In 64-bit VMs without a very large maximum heap size, the JVM usually uses "compressed" pointers, too, so 32-bit values can, in practice, address 32GB of data. Intel CPUs have addressing modes that work quite well with this. See: http://wikis.sun.com/display/HotSpotInternals/CompressedOops
Garbage collection isn’t free, but it’s getting pretty good.
In 64-bit VMs without a very large maximum heap size, the JVM usually uses "compressed" pointers, too, so 32-bit values can, in practice, address 32GB of data. Intel CPUs have addressing modes that work quite well with this. See: http://wikis.sun.com/display/HotSpotInternals/CompressedOops
Garbage collection isn’t free, but it’s getting pretty good.