2016-09-24 67 views
0

引用變量存儲對對象的引用。看來獲得這個引用的唯一方法是調用toString()方法,它返回對象哈希碼而不是地址。有沒有辦法獲得對象的物理地址?是否有可能獲得Java中的對象的物理地址?

class Point { 
int x; 
int y; 
} 
public class MyClass { 
    public static void main(String[] args) { 
    Point p = new Point(); 
} 
} 

我的問題是:「是否有可能獲得p對象的物理地址?」。當然我知道p.toString()返回它的哈希碼。這就是爲什麼我要問有沒有可能獲得地址。我不需要使用它或改變它。我只需要知道是否有可能得到它。

我問這個問題的原因是我在很多不同的地方看到很多相同的問題,但沒有答案。我只需要確認我的建議,這是不可能的。但是在這種情況下出現了新的問題:JVM如何找到對象?

+0

請澄清您的具體問題或添加其他詳細信息,以確切地突出顯示您的需求。正如目前所寫,很難確切地說出你在問什麼。請參閱如何問問頁面以獲取幫助以澄清此問題。 –

+3

對象的物理地址不可訪問,並且可以由JVM隨意更改。 toString()中的「地址」是*身份哈希*,與地址不同。 – Bohemian

+4

您可以使用'sun.misc.Unsafe'來獲取對象的當前物理地址(http://stackoverflow.com/questions/38114099/understanding-how-to-memcpy-with-theunsafe/38189553#38189553)。但垃圾收集器可能會在當時踢,並將對象移動到其他地址。所以你得到的地址可能幾乎從你得到它的那一刻起就失效了。 –

回答

0

。看來獲得這個引用的唯一方法是調用toString()方法,它返回對象哈希碼而不是地址。

hashCode是一個隨機生成的數字,與地址無關。

有沒有辦法獲得對象的物理地址?

你可以用不安全的方式得到它,但是除了興趣外,你不應該這樣做。

JVM如何找到對象?

JVM使用該引用作爲索引。該索引可以是間接的,即可以有一個對象所在的陣列,它可以是例如一個翻譯。 CompressedOops可能會將索引乘以8,並可以選擇添加偏移量。

如果使用Oracle/OpenJDK並禁用CompressedOops,則可以獲得未翻譯的64位地址。

一個簡單的方法做,這是把對象的地址到一個數組 ,然後就好像他們根據你的推薦尺寸爲intlong訪問數組中的元素。

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); 

我有很多其他的例子在這裏

https://github.com/peter-lawrey/Performance-Examples/tree/master/src/main/java/vanilla/java/unsafe

最有用的技巧是能夠看見物體是如何排列,前後GC之後。只能在家裏嘗試。 NSFW。

相關問題