-3

Why there is no way to get current address of an Object in pure java? And how actually == operator works? Is there any possibility to compare references to objects not using this operator?

  • 5
    Why do you need this functionality? Your question looks like [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). – Pshemo Aug 18 '15 at 19:05
  • 2
    `==` compares object identities. Only if the two references point to the same object, `==` will evaluate to true. – PM 77-1 Aug 18 '15 at 19:07
  • @Pshemo I've got two **independent** components. They use objects of the same class. And I want to know whether they use the same instance – Arseny Istlentyev Aug 18 '15 at 19:10
  • 1
    And what is stopping you from using `==`? – Pshemo Aug 18 '15 at 19:11
  • If you want to check if two objects are the same object, use `==`. If you only want to know if the are equal, use `x.equals( y )`. – Florian Schaetz Aug 18 '15 at 19:11
  • Why does == not work for that, then? – Louis Wasserman Aug 18 '15 at 19:11
  • @Louis Wasserman, the components don't know anything about each other. So I can't use ==. If there were a possibility to print addresses of objects, I'd compare them using logs. (Because in my case I don't need to compare objects during the runtime) – Arseny Istlentyev Aug 18 '15 at 19:16
  • The address of an object in Java can change constantly due to garbage collection; they're not pinned in one place. What is the point of checking this in logs? If the components don't know anything about each other, how is it even possible they use the same objects? – Louis Wasserman Aug 18 '15 at 19:25
  • Print the System.identityHashCode(this helps even when the objects overwrites hashCode). Object.hashCode does return distinct integers for distinct objects when this runs in the same JVM. And currently uses the memory address for calculating the hashCode. or use sun.misc.Unsafe if its so important. But you are warned that both can fail totally. – mszalbach Aug 18 '15 at 19:27
  • @Louis Wasserman, this object can be a singleton. Or another component (I have no access to it) can invoke constructors of my two components sending the same object. – Arseny Istlentyev Aug 18 '15 at 19:32
  • 1
    @mszalbach: No, `System.identityHashCode` is not guaranteed to return distinct integers for distinct objects. This is easy to prove: JVMs can allocate more than 2^32 objects, and there are only 2^32 distinct possible return values from `System.identityHashCode`. It's likely that this will be good enough for a crude guess, though. – Louis Wasserman Aug 18 '15 at 19:33
  • @Louis Wasserman yes this makes sense. I just quoted the api and did not think about it. But in the api is a magically "when reasonably practical" so maybe it is guaranteed when having below 2^32 objects but for this some one has to check the native method and even when it can be changed next release. – mszalbach Aug 18 '15 at 19:48
  • @Louis Wasserman: I think that System.identityHashCode is sufficient in 99% cases. Even if not guarranteed by specification, in reality it should work. In order to allocate 2^32 objects, it would take up around 160 GB of RAM (2^32 is 4GB if an object takes a byte, but smallest Java object is at least around 40B big). You can see now even Terabytes of RAM on Oracle or IBM supercomputers, but still I would not expect a single Java VM use that much memory. – OndroMih Aug 18 '15 at 20:31
  • @OndrejM Sure, that's how many you'd need to *force* a collision. But you don't need that many to get an organic collision. http://stackoverflow.com/questions/16105420/java-object-hashcode-address-or-random mentions ways to control the algorithm used for `hashCode()`. Interestingly enough, when I used mode 4 -- memory addresses -- I could usually produce a collision in about ~1.8M objects, which is quite easy; I couldn't get a collision if I used the default (random) `hashCode` implementation, which I found surprising since probability theory says to expect a collision after ~2^16 elements. – Louis Wasserman Aug 18 '15 at 20:43
  • @Louis Wasserman, you are certainly right - with JVM, nothing prevents hashCode collisions even for less objects. However, with 2 given objects, the probability that these 2 particular objects are in collision is very low. And I belive that this case is Arseny in particular interested in. In reality, you System.identityHashCode is as close as it gets to represent a logical address of an objects in terms of comparison to another object. – OndroMih Aug 20 '15 at 12:26

3 Answers3

0

Q1: No way to get obj's mem location: Original creators of Java decided that this was not necessary to the language. Moreover, Java is now quite a old/venerable language, and it has never been added to the language, which means no one ever needed it.

Q2. how == works: this returns true if two values on the stack are the same value. I believe that the java language specification demands that these two objects / primatives be of the same type. I don't know if you could hack this in the bytecode... The answer to this may be JVM specific.

ControlAltDel
  • 33,923
  • 10
  • 53
  • 80
0

Java language does not provide an address of objects in memory. It makes little sense as objects may be freely moved around by garbage collector.

However, what you probably seek is hashcode of an object. In Java, every object has a hashCode() function, that by default returns same number for same objects, and different number for different objects. Hence, hashCode() gives you effectively a logical address of the object in memory. You cannot use the address to modify data in memory as you could in C language, but you could compare objects using its value.

As the hashCode() method can be overwritten in objects, java.lang.System class provides a method to retrieve original value of hashCode() function if it wasn't overriden: System.identityHashCode

OndroMih
  • 7,280
  • 1
  • 26
  • 44
0

For Oracle-JVM:
The method Object.toString() delivers an object identifier with pattern <class>@<address>. The method can with some workaround be called for instances of arbitrary classes, to extract that address.

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;


class ObjectInfo
{
    static long getAddress(Object obj)
    {
        try
        {
            final Field IMPL_LOOKUP = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
            IMPL_LOOKUP.setAccessible(true);
            final MethodHandles.Lookup lkp = (MethodHandles.Lookup) IMPL_LOOKUP.get(null);
            final MethodHandle h1 = lkp.findSpecial(Object.class, "toString", MethodType.methodType(String.class), Object.class);
            final String result = (String) h1.invoke(obj);
            final String[] parts = result.split("@");
            return Long.parseLong(parts[1], 16);
        }
        catch (final Throwable e)
        {
            e.printStackTrace();
            return 0;
        }
    }
}

NOTE: The proof that the identifier address coincides with the memory address of the Object is not done, here.