您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Java直接內存訪問的技巧有哪些,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
Java被設計成一個安全,可管理的環境,然而 Java HotSpot有一個后門,提供了對低級別的,對直接內存和線程的操作。這個后門是—-sun.misc.Unsafe。這個類在JDK中有廣泛的應用,例如,java.nio和java.util.concurrent。很難想象在日常開發中使用這些危險的,不可移植和未經校驗的API。然而,Unsafe提供一種簡單的方法來觀察HotSpot JVM內部的一些技巧。
sun.misc.Unsafe這個類的訪問是受限的,它的構造方法是私有的,相應的工廠方法要求必須被Bootloader載入才能使用,也就是說,只有JDK內部分才能使用這個工廠方法來構造Unsafe對象。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
幸運地是,有一個theUnsafe屬性可以被利用來檢索Unsafe實例,我們可以見到的寫一個反射方法,來獲取Unsafe實例:
1 2 3 4 5 6 7 |
|
下面將學習一些Unsafe的方法。
1.long getAddress(long address) 和void putAddress(long address, long x)
對直接內存進行讀寫。
2.int getInt(Object o, long offset) , void putInt(Object o, long offset, int x)
另一個類似的方法對直接內存進行讀寫,將C語言的結構體和Java對象進行轉換。
3.long allocateMemory(long bytes)
這個可以看做是C語言的malloc()函數的一種包裝。
Java對象的結構如下圖所示:
第一個技巧,是模擬C語言的sizefo()函數,這個函數返回對象的字節大小。我們可以用如下的代碼實現sizeof()函數:
1 2 3 4 5 6 7 8 9 |
|
我們需要使用normalize()函數,因為如果內存地址如果在2^31和2^32之間,將會自動的覆蓋鄰近的整型,也就是說用補碼的方式進行存儲。讓我們在32位JVM(JDK6或者7)中進行測試:
1 2 3 4 5 |
|
Unsafe允許通過allcateMemory和freeMemory方法對內存進行顯示的分配和回收,直接分配的內存不在GC的控制內,并且不受限于JVM堆的大小。通常,通過NIO的脫離堆約束的緩沖,這些方法是安全有效的,但是有趣的是這讓標準的Java引用映射非堆內存變成了可能:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
所以,事實上是可以對真實對象進行內存分配和回收的,不單單只是NIO中的字節緩沖。當然,有一個比較大的問題是,GC將會在這樣的內存欺騙之后發生。
想象一下有一個以String為參數的方法,但它需要經行外部的重載。具體代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
為了讓這段代碼能工作,首先需要更改Carrier類去偽裝成String的子類。superclasses列表被存儲在Carrier類結構體28的位置,如上文圖中所示。原則上,添加如下的代碼可以讓Carrer轉化成String:
1 2 3 |
|
這樣,類型轉化可以正常工作。然而,這樣的轉換方式是不切當并且違反虛擬機規范的。更詳細的方法將包含如下的步驟:
1.在Carrier類中32的位置實際上包含了一個指向Carrier類自己的指針,所以這個指針將被轉移到36的位置上,不僅僅是被指針重寫到String類。
2.當Carrier繼承自String的時候,String類的final標記將被移掉。
sun.misc.Unsafe提供了幾乎是不受限制的監控和修改虛擬機運行時數據結構的能力。盡管這些能力幾乎是和Java開發本身不相干的,但是對于想要學習HotSpot虛擬機但是沒有C++代碼調試,或者需要去創建特別的分析工具的人來說,Unsafe是一個偉大的工具。
以上就是Java直接內存訪問的技巧有哪些,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。