Java中如何获取对象(引用)地址?
上周有同学问,对象的hashcode是否就是它的地址?如何获取Java中一个对象的地址? 首先我们来看第一个问题——对象的hashcode是否是它的地址,这个问题的答案是这个取决于具体的实现,一般来说,它常常是对象的初始地址的整数表示。我们可以从JDK中Object类中hashcode()方法的注释看出来: 其中,重点是这句
* 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.
翻译成中文是,这个方法的典型实现是通过把对象的内部地址转为为整数,但是这种实现技术并不是Java编程语言所规定的。 为什么我还在最上面的回答加上一个初始地址呢?因为Java中的对象是JVM在管理,JVM会在她认为合适的时候对对象进行移动,比如,在某些需要整理内存碎片的GC算法下发生的GC。既然,对象的地址会变动,那么第二个问题还有意义么?对不起,确实没意义。但是我们仍然有权利知道我们想知道的一切,下面的代码展示了如何获取对象的地址,同时也对GC前后对象的地址进行了输出,便于比较。
import sun.misc.Unsafe; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collections; public class OrderOfObjectsAfterGCMain { static final Unsafe unsafe = getUnsafe(); static final boolean is64bit = true; public static void main(String... args) { Double[] ascending = new Double[16]; for(int i=0;i<ascending.length;i++) ascending[i] = (double) i; System.out.println("Before GC"); printAddresses("ascending", ascending); System.gc(); System.out.println(" After GC"); printAddresses("ascending", ascending); } public static void printAddresses(String label, Object... objects) { System.out.print(label + ": 0x"); long last = 0; int offset = unsafe.arrayBaseOffset(objects.getClass()); int scale = unsafe.arrayIndexScale(objects.getClass()); switch (scale) { case 4: long factor = is64bit ? 8 : 1; final long i1 = (unsafe.getInt(objects, offset) & 0xFFFFFFFFL) * factor; System.out.print(Long.toHexString(i1)); last = i1; for (int i = 1; i < objects.length; i++) { final long i2 = (unsafe.getInt(objects, offset + i * 4) & 0xFFFFFFFFL) * factor; if (i2 > last) System.out.print(", +" + Long.toHexString(i2 - last)); else System.out.print(", -" + Long.toHexString( last - i2)); last = i2; } break; case 8: throw new AssertionError("Not supported"); } System.out.println(); } private static Unsafe getUnsafe() { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); return (Unsafe) theUnsafe.get(null); } catch (Exception e) { throw new AssertionError(e); } } }
created by 刘Sir