64

How do Object.hashCode() and System.identityHashCode() work at the back end? Does identityHashCode() return the reference of the object? Does hashCode() depend on the content or address of the object?

What is the difference between hashCode() and identityHashCode()?

1

7 Answers 7

49

How do Object.hashCode() and System.identityHashCode() work at the back end?

Assuming that it hasn't been overridden, the Object.hashCode() method simply calls System.identityHashCode(this).

The exact behavior of System.identityHashCode(Object) depends on the JVM implementation. (The actual implementation on recent Hotspot JVMs is rather clever, but I digress.)

Does identityHashCode() return the reference of the object?

No. It returns an int, and an int cannot hold a reference.

That integer returned by identityHashCode may be related to the (a) machine address for the object, or it may not be1. The value returned by identityHashCode() is guaranteed not to change for the lifetime of the object. This means that if the GC relocates an object (after an identityHashCode() call) then it cannot use the new object address as the identity hashcode.

Does hashCode() depend on the ? of the object ? == operator how to work in back end.

This doesn't make sense. There is no ? == or ?== operator in Java.

What is the difference between hashCode() and identityHashCode()?

This is partly explained above. Other differences include:

  • The hashCode() method is a non-final instance method, and should be overridden in any class where the equals(Object) is overridden. By contrast, identityHashCode(Object) is a static method and therefore cannot be overridden.

  • The identityHashCode(Object) method gives you a identifier for an object which can (in theory) be used for other things than hashing and hash tables. (Unfortunately, it is not a unique identifier, but it is guaranteed to never change for the lifetime of the object.)


1 - For current generation JVMs, it is not related to the memory address at all. See @bestsss's answer.

Sign up to request clarification or add additional context in comments.

2 Comments

Can you digress and explain how the JVMs today implement it?
That is a separate question, or ... something that you can figure out for yourself by reading the source code, or ... read the other answers and comments. (I assume that this is solely for your curiosity.)
31

identityHashCode() works like that (and as of now it has nothing do to with the address, especially since the addresses are 64bits long, ok aligned, so 61):

Checks if there is already generated one, if so returns it. You can assume there is a place in the object header for that int;

Otherwise: Generates a random number (Marsaglia shift-xor algorithm). Every native thread has its own seed, so no shared info. CAS the identityHashCode field in the object header to update w/ the newly generated number. If CAS succeeds, returns the value. If not, the field already contains a generated identityHashCode.

You can see the rest of the replies about overriding hashcode.

Bottom line: If the JavaDoc still states anything about addresses and identityHashCode, someone needs to update it.

1 Comment

There are 5 alternatives of hash code calculation in the code. Looking at this one can see that option 5, Marsaglia shift-xor, is really currently used. Hashcode generation has been elaborated more in this blog post
13

This is pretty much implementation specific. The only guarantee you get is

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

(From the Java 1.6 JavaDoc)

In theory, this means that the values could be determined arbitrarily and could even be zero for every object. In practice, it's probably something derived from the address of the object. Of course, you have to be careful about this. The JVM can relocate objects if it thinks it's a good idea during a garbage collection, so it's not going to be "just" the memory address. It could be drawn from a global counter, or a hash of the original object's location, or from a random number generator, etc.

4 Comments

You're right, I must have mixed something up. I got stuck in the documentation to back my hypotesis -- but failed. ;-) deleted my answer and upvoted yours!
what is the difference between hashCode() and identityHashCode()?
@Himanshu- Object.hashCode() is the default implementation of hashCode() and is often overridden by derived classes to conform to the rules for equals()/hashCode(). System.identityHashCode() provides a way to get the value that Object.hashCode() would return for that object even if it contains an override for this method. This allows you to make containers that work with identity semantics, since == and System.identityHashCode() treat each object uniquely.
The idea that hashCode uses the memory address is a historical artefact stackoverflow.com/questions/36236615/…
10

Lots of answers given above, just need to add some points.

When we say obj.hashCode() the content of the obj is considered, on the other hand in System.identityHashCode(obj) the content are not taken in consideration, thus identityHashCode for two different String, int(with same value) will be the different but Hashcode will be the same.

In case of String to get identityHashCode string pool plays important role, example

 Object s1 = "abcd"; Object s2 = new String("abcd"); Object s3 = "abcd"; System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode()); System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode()); System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode()); //output: identityHashCode : 2018699554 HashCode : 2987074 identityHashCode : 1311053135 HashCode : 2987074 identityHashCode : 2018699554 HashCode : 2987074 

here s1 and s3 pointing same ref therefore identityHashCode for s1 and s3 is always same and s2 will be different.

Same for int also, IntegerCache plays the important role to get the identityHashCode

 Object s1 = 5; Object s2 = new Integer(5); Object s3 = 5; System.out.println("identityHashCode : " + System.identityHashCode(s1) + " HashCode : " + s1.hashCode()); System.out.println("identityHashCode : " + System.identityHashCode(s2) + " HashCode : " + s2.hashCode()); System.out.println("identityHashCode : " + System.identityHashCode(s3) + " HashCode : " + s3.hashCode()); //Output identityHashCode : 2018699554 HashCode : 5 identityHashCode : 1311053135 HashCode : 5 identityHashCode : 2018699554 HashCode : 5 

Comments

5

identityHashCode

public static int identityHashCode(Object x)

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

See [Java docs]

So if someone has overridden hashCode() method in its class but still want the default hashCode() value which would have been returned by Object hashCode() then use System.identityHashCode()

So, hashCode() internally calls System.identityHashCode() as long as you are not overriding it in you class, if you override hashCode() it will call your implementation.

Comments

0

A very well understanding you will get from below code:

identityHashCode() will give you the memory address (a number) of String literal in String pool whereas hashcode() method of Object class will give you the same hash value for all the objects which are same (having same string literal)

 String a = new String("abc"); // "abc" will not be added to String constant pool. System.out.println(System.identityHashCode(a)); // 460141958 String b = a.intern();// add s to String constant pool System.out.println(System.identityHashCode(b)); // 1163157884 String c = "abc"; // OR String c = b; System.out.println(System.identityHashCode(c)); // 1163157884 String d = new String("abc"); // OR String d = new String(c) System.out.println(System.identityHashCode(d)); // 1956725890 String e = new String(new char[]{'a', 'b', 'c'}); System.out.println(System.identityHashCode(e)); // 356573597 System.out.println(e.intern() == b); //true System.out.println(); String str2 = "hello"; String str1 = new String("hello"); String str3 = str1.intern(); System.out.println(System.identityHashCode(str2)); // 1735600054 System.out.println(System.identityHashCode(str1)); // 21685669 System.out.println(System.identityHashCode(str3)); // 1735600054 System.out.println(str2 == str3); // true System.out.println(str3 == str1); // false String str4 = new String(new char[]{'h', 'e', 'l', 'l', 'o'}); //// "hello" will not be added to String constant pool. System.out.println(str4.intern() == str2); //true 

1 Comment

The code provided is very explanatory, but the introductory explanation is not entirely correct. identityHashCode does not return a memory address. It returns the result of hashCode() as if it wasn't overridden from Object's default implementation.
0

A lot of good answers has been given above but it seems to me that lacks a conceptual cornerstone: the distinction between state and instance identity.

If hashCode() method is not overridden in a class, it means that two instances of that class, even if they have the same state (i.e. identical class fields) and therefore are not substantially distinguishable, remain two distinct objects, with their own identity. For example, if they are added to a Set, they occupy two different slot in the underlying Map.

If instead you redefine hashCode() you usually do this to identify an instance of the class with its state. For example, if you have a Person class with the name (String) and age (int) fields, in hashCode() you will create a function that uniquely maps the name/age pair so that if you have two distinct instances of Person but with the same values ​​for name and age, in Java they will be treated as the same instance respect to equals operator. If you add them to a Set, for example, they occupy the same slot. A lot of objects in JDK do this thing, for example java.io.File class.

Even if the hashCode() method is redefined in a class to reflect its state, two instances with identical state are still two distinct objects for the JVM, each occupying its own memory area. The identity hash of these objects, stored in the object header (in the mark word), is always distinct because it is calculated by the JVM and this value is the one returned by System.identityHashCode() .

Returning to the Person class example the following code

 Person p1 = new Person("jack", 20); Person p2 = new Person("jack", 20); System.out.println(p1.equals(p2)); System.out.println(p1 == p2); 

returns both false if hashCode() method is not overwritten, otherwise return true and false.

Note that == operator doesn't care of hashCode() method: it simply compares if two object references points to the same physical object, regardless of its state, and so uses always System.identityHashCode().

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.