As I am studying java, I have learned that the proper way to compare 2 Strings is to use equals and not "==". This line
static String s1 = "a"; static String s2 = "a"; System.out.println(s1 == s2);
will output true because the jvm seems to have optimized this code so that they are actually pointing to the same address. I tried to prove this using a great post I found here
http://javapapers.com/core-java/address-of-a-java-object/
but the addresses don't seem to be the same. What am I missing?
import sun.misc.Unsafe; import java.lang.reflect.Field; public class SomeClass { static String s1 = "a"; static String s2 = "a"; public static void main (String args[]) throws Exception { System.out.println(s1 == s2); //true Unsafe unsafe = getUnsafeInstance(); Field s1Field = SomeClass.class.getDeclaredField("s1"); System.out.println(unsafe.staticFieldOffset(s1Field)); //600 Field s2Field = SomeClass.class.getDeclaredField("s2"); System.out.println(unsafe.staticFieldOffset(s2Field)); //604 } private static Unsafe getUnsafeInstance() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafeInstance.setAccessible(true); return (Unsafe) theUnsafeInstance.get(Unsafe.class); } }
Best Answer
I think you're confused on what
staticFieldOffset
is returning. It's returning the offset of the pointer to theString
instance, not the address of theString
itself. Because there are two fields, they have different offsets: ie, two pointers, which happen to have the same value.A close reading of the Unsafe javadoc shows this:
In other words, if you know where the actual
Class
instance is in memory, then you could add the offset returned by this method to that base address, and the result would be the location in memory where you could find the value of the pointer to theString
.