Ramblings from a Bihari!

Just another WordPress.com weblog

interesting fact about identityHashCode() method in java.lang.System Class

The following four lines of code is provides such outputs which confused me about the identityHashCode() method of System class. System.identityHashCode() method is supposed to give the default hashcode value irrespective of whether you have overridden hascode in your class. And as we know that default implementation maps the internal memory address to an integer value.

1  String s = new String(new char[]{‘j’, ‘a’,’v’,’a’});
2  String s1 = new String(new char[]{‘a’, ‘b’,’c’,’d’});

3  System.out.println(System.identityHashCode(s));
4  System.out.println(System.identityHashCode(s1));

When I created a String instance by executing line 1 it would have got some memory location allocated to it. Lets say that is “x”. Then I created another instance s1 with passing some other different array to the String constructor. So s1 would have also got some memory location  allocated for it. Lets say that is “y”.

Now when I print the identity hash code by executing the line number 3 and 4 every time I run the program it gives me the same two integer values. And the order of values depends on the execution of line number 3 and 4 but not on 1 and 2 where actual allocation of memory happened. Thats strange for me 😦

July 31, 2008 - Posted by | techie stuff

8 Comments »

  1. It’s strange for me also.
    I was playing with your piece of code when I realized that if I debug the values changes.
    Somehow I got that:
    ————–
    String str1 = new String(“abcd”);
    String str2 = new String(“efgh”);
    try {
    long time = (long) (Math.random() * 10000.0) ;
    System.out.println(“Sleeping: ” + time);
    Thread.sleep(time);
    } catch (InterruptedException e) {
    /**/
    }
    System.out.println(System.identityHashCode(str1));
    System.out.println(System.identityHashCode(str2));
    }
    ———

    So it seems to me that the identityHashCode is related to the elapsed time since the jvm is started and the hash is computed.

    Comment by Oni | July 31, 2008 | Reply

  2. hi oni

    But javadoc of identityHashCode() suggests that it is the default implementation of hashcode which is essentially the Object’s implementation of hashcode. That implementation is just the integer mapping of memory location and not at all related to the time jvm has been active.

    Comment by deepakjha | July 31, 2008 | Reply

  3. Hi,
    well, as far as I understand, it’s calling a native method:
    public static native int identityHashCode(Object x);
    But, I suppose the same as you, is calling the Object.hashCode().
    I’ve not checked the impelentation of Object.hasCode(). A quick “google” give me this, somehow interesting, result:
    http://erikengbrecht.blogspot.com/2008/07/systemidentityhashcode.html
    Btw, I’m running on a linux 32 bits 1.6 JVM.
    Did the same as me happened to you? does the value change because of time?

    Comment by Oni | July 31, 2008 | Reply

  4. No oni for me the values didn’t change. It was coming the same for consecutive runs of your code sample.

    Comment by deepakjha | August 1, 2008 | Reply

  5. For me the output is:

    4072869
    1671711

    Comment by Dave | October 8, 2008 | Reply

  6. Think about it — it’s a memory address. Assume the JVM is a deterministic finite state machine. Each run should go through the same internal states. So each run should be assigning the same memory locations. Now if another program is also running on that JVM and the timing relationships are flexible (as would be the case for some debuggers or multi-threaded applications), then the addresses would change with the changes to the allocation order of the objects.

    Comment by Jeslie | December 5, 2008 | Reply

  7. If lines 1-4 are indeed your entire program, then my guess is that the jvm is inlining the instantiation of the Strings (from line 1-2) into lines 3-4, which is the only place they are used. That would explain why reordering lines 3-4 has the only effect on your output.

    In general be wary of making assumptions about why something is happening based on the order of statements in your source code – barring synchronization, the jvm has wide latitude to reorder and optimize the bytecode at runtime.

    Comment by Scott Bale | September 8, 2009 | Reply

  8. Dear friends,

    Here is a piece of code that more generally aims to produce a clash in which two dissimilar objects (obj1 != obj2) produce the same hashCode() result. It is interesting that on my system only 1756 instantiations are needed before a clash is found (if the hash code algorithm can be modeled by a random distribution, this is a special instance of the birthday paradox I suppose).

    import java.util.Hashtable;
    import java.util.Map;

    public class HashcodeTest{
    static class DummyObject extends Object { }

    public static void reportClash(DummyObject obj1, DummyObject obj2) {
    System.out.println(“obj1.hashCode() = ” + obj1.hashCode());
    System.out.println(“obj2.hashCode() = ” + obj2.hashCode());
    System.out.println(“(obj1 == obj2) = ” + (obj1 == obj2) + ” (!)”);
    }

    public static void main(String[] args) {
    Map map = new Hashtable();
    for (int count = 1; true; count++) {
    DummyObject obj = new DummyObject();
    if (map.containsKey(obj.hashCode())) {
    System.out.println(
    “Clash found after instantiating ” + count + ” objects.”);
    reportClash(map.get(obj.hashCode()), obj);
    System.exit(0);
    }
    map.put(obj.hashCode(), obj);
    }
    }
    }

    For me that exemplifies that hashCode() even by all practical means is useless to serve as an object identity.

    Cheers,
    Frank

    Comment by Frank | March 6, 2011 | Reply


Leave a reply to Oni Cancel reply