131

I would like to print the "object reference" of an object in Java for debugging purposes. I.e. to make sure that the object is the same (or different) depending on the situation.

The problem is that the class in question inherits from another class, which has overriden both toString() and hashCode() which would usually give me the id.

Example situation: Running a multi-threaded application, where I (during development) want to check if all the threads use the same instance of a resource object or not.

Nicolai
  • 3,698
  • 3
  • 30
  • 34
  • 1
    depending on if you can do it at all... == is the way to go... but I have no idea how the code in question is stuctured. Again hashCode is likely fine for what you are doing, but it could break depending on how the library is implemented. – TofuBeer Feb 24 '09 at 09:21
  • 1
    It is really a good question. – Zhang Xiang Nov 08 '16 at 05:40

6 Answers6

120

What exactly are you planning on doing with it (what you want to do makes a difference with what you will need to call).

hashCode, as defined in the JavaDocs, says:

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 Java™ programming language.)

So if you are using hashCode() to find out if it is a unique object in memory that isn't a good way to do it.

System.identityHashCode does the following:

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.

Which, for what you are doing, sounds like what you want... but what you want to do might not be safe depending on how the library is implemented.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
TofuBeer
  • 60,850
  • 18
  • 118
  • 163
  • 6
    I am not acting on the value in the code. As pr. my question edit, I only use it for debugging purposes of a certain situation. That is why I feel my answer is reasonable, but I give you a +1 for an insightful reply. – Nicolai Feb 24 '09 at 09:11
  • 1
    odds are it will always do what you want - but it could break on some VMs. – TofuBeer Feb 24 '09 at 09:12
  • It'll break (i.e. identityHashCode will not necessarily be unique) on any reasonable VM. identityHashCode is not an I.D. – Tom Hawtin - tackline Feb 24 '09 at 11:33
  • As has been mentioned, there is no guarentee of the hashcode being based on the address. I have seen multiple objects with the same ID occur in the IBM VM inside of WAS. – Robin Feb 24 '09 at 14:48
  • "This is typically implemented by converting the internal address of the object into an integer" not a gurantee, but the default implementation from Sun. Things like s = "Hello" and t = "Hello" would probably result in s and t having the same identityHashCode as they really are the same object. – TofuBeer Feb 24 '09 at 15:23
  • @TofuBeer: those two would definitely get the same value, as they are the same objects, as defined by the JLS and/or JVM spec (I always remember which one) – Joachim Sauer Jul 20 '09 at 09:00
58

This is how I solved it:

Integer.toHexString(System.identityHashCode(object));
Nicolai
  • 3,698
  • 3
  • 30
  • 34
  • 7
    This is not actually correct, since multiple objects can return the same identityHashCode. – Robin Feb 24 '09 at 14:49
  • 2
    Isn't it true that two objects (references) with the same identity hash are the same object? that's what to OP wants – basszero Feb 24 '09 at 15:11
  • 4
    No, it isn't true. It's very likely, but not guaranteed as the spec does NOT define the algorithm. – Robin Sep 24 '13 at 02:16
10

Double equals == will always check based on object identity, regardless of the objects' implementation of hashCode or equals. Of course - make sure the object references you are comparing are volatile (in a 1.5+ JVM).

If you really must have the original Object toString result (although it's not the best solution for your example use-case), the Commons Lang library has a method ObjectUtils.identityToString(Object) that will do what you want. From the JavaDoc:

public static java.lang.String identityToString(java.lang.Object object)

Gets the toString that would be produced by Object if a class did not override toString itself. null will return null.

 ObjectUtils.identityToString(null)         = null
 ObjectUtils.identityToString("")           = "java.lang.String@1e23"
 ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
noahlz
  • 10,202
  • 7
  • 56
  • 75
  • 2
    If you are using Java 7, then you should consider using [java.util.Objects](http://docs.oracle.com/javase/7/docs/api/java/util/Objects.html) – noahlz Mar 22 '12 at 20:08
  • 2
    with respect to your comment, what method(s) in `java.util.Objects` did you have in mind? `Objects.toString(o)` is equivalent to calling o.toString(), with null checking, which doesn't seem to be relevant to this question. – amaidment Sep 23 '20 at 09:55
  • 1
    @amaidment Ok, yes Object.toString just calls toString on the reference, avoiding NPEs – noahlz Sep 24 '20 at 13:27
5

You cannot safely do what you want since the default hashCode() may not return the address, and has been mentioned, multiple objects with the same hashCode are possible. The only way to accomplish what you want, is to actually override the hashCode() method for the objects in question and guarantee that they all provide unique values. Whether this is feasible in your situation is another question.

For the record, I have experienced multiple objects with the same default hashcode in an IBM VM running in a WAS server. We had a defect where objects being put into a remote cache would get overwritten because of this. That was an eye opener for me at that point since I assumed the default hashcode was the objects memory address as well.

Robin
  • 24,062
  • 5
  • 49
  • 58
3

Add a unique id to all your instances, i.e.

public interface Idable {
  int id();
}

public class IdGenerator {
  private static int id = 0;
  public static synchronized int generate() { return id++; }
}

public abstract class AbstractSomething implements Idable {
  private int id;
  public AbstractSomething () {
    this.id = IdGenerator.generate();
  }
  public int id() { return id; }
}

Extend from AbstractSomething and query this property. Will be safe inside a single vm (assuming no game playing with classloaders to get around statics).

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
  • I would probably use AtomicInteger in this scenario - it has a higher throughput because synchronization is not required and it uses native atomic memory operations provided by `sun.misc.Unsafe` – randers Feb 08 '16 at 07:34
2

we can simply copy the code from tostring of object class to get the reference of string

class Test
{
  public static void main(String args[])
  {
    String a="nikhil";     // it stores in String constant pool
    String s=new String("nikhil");    //with new stores in heap
    System.out.println(Integer.toHexString(System.identityHashCode(a)));
    System.out.println(Integer.toHexString(System.identityHashCode(s)));
  }
}
takrl
  • 6,356
  • 3
  • 60
  • 69