Phương thức toString của đối tượng là duy nhất ở chỗ nó có vẻ là nơi duy nhất trong Java nơi địa chỉ bộ nhớ có thể xem được. Object làm như thế nào?
Địa chỉ không nhận được địa chỉ, trong JVM HotSpot, nó nhận được mã băm 31 bit được tạo ngẫu nhiên được lưu trữ trong tiêu đề của đối tượng.Điều này phải được lưu trữ bởi vì;
- mã băm không thể thay đổi ngay cả khi đối tượng được di chuyển và có địa chỉ mới.
- địa chỉ không đủ ngẫu nhiên. 8 bit thấp hơn của địa chỉ luôn là 0. Sau mỗi GC, đối tượng đầu tiên được tạo luôn giống nhau.
- địa chỉ có thể là 64 bit.
LÀM TRY NÀY TẠI NHÀ, KHÔNG THÍCH HỢP CHO CÔNG VIỆC !!
Bạn có thể nhận/đặt hashCode() sử dụng Unsafe
static final Unsafe UNSAFE;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
}
public static void setIdentityHashCode(Object o, int code) {
UNSAFE.putInt(o, 1l, code & 0x7FFF_FFF);
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
Double d = 1.0;
Double d2 = 1.0;
setIdentityHashCode(d, 1);
setIdentityHashCode(d2, 1);
System.out.println("d: "+d+" System.identityHashCode(d): "+System.identityHashCode(d));
System.out.println("d2: "+d2+" System.identityHashCode(d2): "+System.identityHashCode(d2));
System.out.println("d == d2: " + (d == d2));
}
in
d: 1.0 System.identityHashCode(d): 1
d2: 1.0 System.identityHashCode(d2): 1
d == d2: false
Bạn có thể lấy địa chỉ từ các giá trị tham khảo miễn là bạn biết làm thế nào bộ nhớ đã được dịch. Trong trường hợp đơn giản nhất, (nơi bạn có tham chiếu 64 bit) tham chiếu chưa được dịch và địa chỉ là giá trị được lưu trữ trong tham chiếu.
Nếu bạn chạy trên một JVM 64-bit với -XX:-UseCompressedOops
// This only works if a GC doesn't move the object while attempting to access it.
static final Unsafe UNSAFE;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
UNSAFE = (Unsafe) theUnsafe.get(null);
} catch (Exception e) {
throw new AssertionError(e);
}
}
// run with: -ea -XX:-UseCompressedOops
public static void main(String[] args) {
Object i = 0x12345678;
System.out.printf("indentityHashCode = %08x%n", System.identityHashCode(i));
Object[] obj = { i };
assert Unsafe.ARRAY_OBJECT_INDEX_SCALE == 8; // 8 bytes per reference.
long address = UNSAFE.getLong(obj, (long) Unsafe.ARRAY_OBJECT_BASE_OFFSET);
System.out.printf("%x%n", address);
for (int j=0;j<24;j++)
System.out.printf("%02x ", UNSAFE.getByte(address + j) & 0xFF);
System.out.println();
// now some really scary sh!t
UNSAFE.putLong(i, 8L, UNSAFE.getLong(0L, 8L));
System.out.printf("`i` is now a %s and is %x%n", i.getClass(), i);
}
in
indentityHashCode = 5a07e868
7fbf41cb8560
01 68 e8 07 5a 00 00 00 48 33 3f b9 b9 7f 00 00 78 56 34 12 00 00 00 00
^^hashCode^ ^class address^ ^int value^
`i` is now a class java.lang.Long and is 12345678
Bạn đã thử kiểm tra mã nguồn của lớp đối tượng – Panther
Câu hỏi bắt buộc: tại sao bạn muốn làm điều đó? – fge
Hãy xem tài liệu API. Đó không phải là địa chỉ bộ nhớ. Và có một cách để có được giống nhau mà không sử dụng 'toString()'. –