What is an object's hash code if hashCode() is not overridden?

19,013

Solution 1

Typically, hashCode() just returns the object's address in memory if you don't override it.

From 1:

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.)

Solution 2

In HotSpot JVM by default on the first invocation of non-overloaded Object.hashCode or System.identityHashCode a random number is generated and stored in the object header. The consequent calls to Object.hashCode or System.identityHashCode just extract this value from the header. By default it has nothing in common with object content or object location, just random number. This behavior is controlled by -XX:hashCode=n HotSpot JVM option which has the following possible values:

  • 0: use global random generator. This is default setting in Java 7. It has the disadvantage that concurrent calls from multiple threads may cause a race condition which will result in generating the same hashCode for different objects. Also in highly-concurrent environment delays are possible due to contention (using the same memory region from different CPU cores).
  • 5: use some thread-local xor-shift random generator which is free from the previous disadvantages. This is default setting in Java 8.
  • 1: use object pointer mixed with some random value which is changed on the "stop-the-world" events, so between stop-the-world events (like garbage collection) generated hashCodes are stable (for testing/debugging purposes)
  • 2: use always 1 (for testing/debugging purposes)
  • 3: use autoincrementing numbers (for testing/debugging purposes, also global counter is used, thus contention and race conditions are possible)
  • 4: use object pointer trimmed to 32 bit if necessary (for testing/debugging purposes)

Note that even if you set -XX:hashCode=4, the hashCode will not always point to the object address. Object may be moved later, but hashCode will stay the same. Also object addresses are poorly distributed (if your application uses not so much memory, most objects will be located close to each other), so you may end up having unbalanced hash tables if you use this option.

Solution 3

The implementation of hashCode() may differ from class to class but the contract for hashCode() is very specific and stated clearly and explicitly in the Javadocs:

Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable.

The general contract of hashCode is:

  • Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
  • If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
  • It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.

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.)

hashCode() is closely tied to equals() and if you override equals(), you should also override hashCode().

Solution 4

The default hashCode() implementation is nothing to do with object's memory address. In openJDK, in version 6 and 7 it is a randomly generated number. In 8 and 9, it is a number based on the thread state.

Refer this link: hashCode != address

So the result of identity hash generation(the value returned by default implementation of hashCode() method) is generated once and cached in the object's header.

If you want to learn more about this you can go through OpenJDK which defines entry points for hashCode() at

src/share/vm/prims/jvm.h

and

src/share/vm/prims/jvm.cpp

If you go through this above directory, it seems hundred lines of functions that seems to be far more complicated to understand. So, To simplify this, the naively way to represent the default hashcode implementation is something like below,

if (obj.hash() == 0) {
    obj.set_hash(generate_new_hash()); 
} 
return obj.hash();

Solution 5

If hashcode is not overriden you will call Object's hashcode, here is an excerpt from its javadoc:

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.)

Share:
19,013

Related videos on Youtube

java_geek
Author by

java_geek

Updated on April 25, 2022

Comments

  • java_geek
    java_geek about 2 years

    If the hashCode() method is not overridden, what will be the result of invoking hashCode() on any object in Java?

    • Ustaman Sangat
      Ustaman Sangat over 12 years
      check out System.identityHashCode() it gives you the default hashcode - the one that would have been returned if you had not overridden the method.
    • mightyWOZ
      mightyWOZ over 2 years
      That depends on the the JVM that you are using. for Hotspot see this
  • Steve Kuo
    Steve Kuo about 14 years
    "hashCode() is closely tied to equals() and if you implement one, you should implement the other" is not entirely correct. You only need to override hashCode if equals is overridden. It is technically valid to override hashCode without overriding equals.
  • Asaph
    Asaph about 14 years
    @Steve Kuo: Fair enough. I re-worded the last sentence based on your comment.
  • Ustaman Sangat
    Ustaman Sangat over 12 years
    I have strong objection to "converting the internal address" and I have been wondering if Sun/Oracle will remove that line from their javadocs. Internal address of the object cannot be guaranteed to remain unchanged in the JVM, whose garbage collector might move it around during heap compaction.
  • Ustaman Sangat
    Ustaman Sangat over 12 years
    OpenJDK hg.openjdk.java.net/jdk6/jdk6-gate/jdk/file/tip/src/share/… has it as a native function. I would like to see the native function implementation...stackoverflow.com/questions/410756/…. Anyone?
  • Ustaman Sangat
    Ustaman Sangat over 12 years
    Maybe the default hashcode method stores the first value and never changes it.
  • Tagir Valeev
    Tagir Valeev over 8 years
    The JavaDoc quote is correct, but the answer is not. Object's address is not used for many years.
  • Sameer
    Sameer over 7 years
    @ernesto No they are not uniques all the time. I tested it on my JVM and found that after 120,000 objects, i start seeing duplicate hashcode. You can read more here stackoverflow.com/questions/40931088/…
  • dkb
    dkb almost 4 years
    This is the best explanation, thank you! since -XX:hashCode=n is an experimental feature, need to enable it first then use above flag, so the combined vm flags are: -XX:+UnlockExperimentalVMOptions -XX:hashCode=4, tested in java-11.
  • Holger
    Holger over 2 years
    As said by others, the documentation’s mentioning of memory addresses was inappropriate, but finally, it got fixed, first the “typically” was removed so it then said that hashCodemay or may not be implemented as some function of an object's memory address at some point in time”, then, the mentioning of addresses got removed completely, removing any source of confusion. Case closed.