1. 程式人生 > >使用sun.misc.Unsafe獲取java物件地址

使用sun.misc.Unsafe獲取java物件地址

在傳統的Java程式設計中,你將不再需要從記憶體中處理Java物件或位置。 當你在論壇上討論這一點,提出的第一個問題是為什麼你需要知道Java物件的地址? 它是一種有效的問題。 但以往,我們保留進行試驗的權利。探索未知領域的問題並沒有什麼錯。我想出了一個使用sun公司包的實驗。Unsafe是一個屬於sun.misc包。對你來說可能這個包有點陌生,看看原始碼和方法,你就可以知道我所指的是什麼了。

Java的安全管理提供了足夠的隱藏來確保你並不能那麼容易的擺弄記憶體。作為第一步,我想到了要得到一個Java物件的記憶體位置。直到探索,我也曾經是100%的信心,這是不可能找到的位置 Java中物件的地址。


Sun的Unsafe.java API文件顯示我們有機會獲得地址使用方法objectFieldOffset。這個方法彷彿在說:“報告中的類儲存分配它的位置在一個特定領域。“ 它還說,“這只是其中一個訪問器的cookie傳遞給不安全堆記憶體“。 無論如何,我能夠從它的類的儲存分配儲存一個物件的記憶體位置。你可以爭辯說,我們所得到的是不是一個物件的絕對實體記憶體地址。但是,我們拿到了邏輯記憶體地址。下面的程式將受到你的有趣!

作為第一步,我得拿到Unsafe類的一個物件。這是很困難的,因為建構函式是私有的。 有一個名為getUnsafe一個方法,該方法返回不安全的物件。Java安全管理要求您給原始碼特權。我用到了一點反射然後得到了一個例項。我知道有更好的方法來獲得例項,但我選擇了以下的方法來繞開安全管理。

使用Unsafe的物件,只需要呼叫objectFieldOffset和staticFieldOffset。結果就是類的記憶體分配地址。

以下的例項程式可以執行在JDK1.6上。

package lock;

import sun.misc.Unsafe;
import java.lang.reflect.Field;

public class ObjectLocation {

    private static int apple = 10;
    private int orange = 10;

    public static void main(String[] args) throws Exception {
        Unsafe unsafe = getUnsafeInstance();

        Field appleField = ObjectLocation.class.getDeclaredField("apple");
        System.out.println("Location of Apple: " + unsafe.staticFieldOffset(appleField));

        Field orangeField = ObjectLocation.class.getDeclaredField("orange");
        System.out.println("Location of Orange: " + unsafe.objectFieldOffset(orangeField));
    }

    private static Unsafe getUnsafeInstance() throws SecurityException, NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException {
        Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafeInstance.setAccessible(true);
        return (Unsafe) theUnsafeInstance.get(Unsafe.class);
    }
}