The JvmtiTagMap uses address-based hashing to map from oops to the associated tag values. This means that any time the GC moves objects in a tagmap it invalidates the hashing. It used to be that the GC was rehashing these tables, but that's being changed to defer rehashing until some JVMTI function needs to use the table (JDK-8212879). This requires the GC to notify JVMTI that (some, possibly relevant) objects have moved.
It may be possible to eliminate the GC-induced rehashing though, by using Java identity hash values instead of object addresses.
Obtaining the identity hash can be done by calling ObjectSynchronizer::FastHashCode. However, we might not want to force a hash code on every JVMTI-examined object.
We can reduce it to only inflicting a hash code on the JVMTI-tagged objects. Whenever we tag an object (via SetTag or by callback handlers), we can ensure an identity hash code has been assigned, using FastHashCode. When looking up an object in the table to see if it has an associated tag, use a variant of FastHashCode (perhaps the same function with an additional argument). This variant detects no hash code recorded, and instead of computing and installing one, returns 0 to indicate no hash. An object with no hash is guaranteed to not be present in the tagmap.
[Note: This problem with JVMTI heap walkers was removed by JDK-8283710.]
Another problem is that JVMTI heap walkers use the markWord to mark objects it has visited (similar to GCs). The real markWord value gets saved in a growable array. So for marked objects we need to reacquire the original mark word (and possibly temporarily reinstall it) in order to obtain its hash code. The currently used marked value is `markWord::prototype().set_marked()`. The prototype is just a dummy value. We could instead use a markWord with the "ptr" field containing the index of the real mark word from the saved array.