I've often heard that these methods (Object.hashCode
and System.identityHashCode
) return the address of the object, or something computed quickly from the address; but I'm also pretty sure the garbage collector moves and compacts objects. Since the hash code cannot change, this presents a problem. I know this is not something one needs to know for everyday work, but I'd like to understand the internals. So, does anyone know how this is implemented in Java? Or .NET, since they are probably similar.
When Java programs run on the JVM, objects are created on the heap, which is a portion of memory dedicated to the program. Eventually, some objects will no longer be needed. The garbage collector finds these unused objects and deletes them to free up memory.
The garbage collector uses a traversal of the object graph to find the objects that are reachable. Objects that are not reached in this traversal are deemed garbage, even if they are part of a cycle of references.
As much as is reasonably practical, the hashCode method defined by class Object does return distinct integers for distinct objects. (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)
Java Object hashCode() is a native method and returns the integer hash code value of the object. The general contract of hashCode() method is: Multiple invocations of hashCode() should return the same integer value, unless the object property is modified that is being used in the equals() method.
.NET's implementation is intentionally not published (and when you attempt to decompile it, you will find that it makes an unmanaged framework call). The only documentation as such is here, which only states that it is "not guaranteed to produce a different value for each object", and "may change between framework versions". Making any assumptions about how it actually works is probably ill-advised.
Java's is more well-understood (though presumably could differ across JVMs), and is covered specifically in this question: Will .hashcode() return a different int due to compaction of tenure space?
The gist of the Java implementation is that by contract, the value of an object's hashcode is not relevant until it is retrieved for the first time. After that, it must remain constant. Thus the GC moving the object doesn't matter until the object's hashcode() method is called for the first time. After that, a cached value is used.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With