欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Java直接內(nèi)存訪問的技巧有哪些

本篇文章給大家分享的是有關(guān)Java直接內(nèi)存訪問的技巧有哪些,小編覺得挺實用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創(chuàng)新互聯(lián)公司專注于水磨溝企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站設(shè)計,商城網(wǎng)站制作。水磨溝網(wǎng)站建設(shè)公司,為水磨溝等地區(qū)提供建站服務(wù)。全流程專業(yè)公司,專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

Java直接內(nèi)存訪問的技巧

Java被設(shè)計成一個安全,可管理的環(huán)境,然而 Java HotSpot有一個后門,提供了對低級別的,對直接內(nèi)存和線程的操作。這個后門是—-sun.misc.Unsafe。這個類在JDK中有廣泛的應(yīng)用,例如,java.nio和java.util.concurrent。很難想象在日常開發(fā)中使用這些危險的,不可移植和未經(jīng)校驗的API。然而,Unsafe提供一種簡單的方法來觀察HotSpot JVM內(nèi)部的一些技巧。

獲取Unsafe

sun.misc.Unsafe這個類的訪問是受限的,它的構(gòu)造方法是私有的,相應(yīng)的工廠方法要求必須被Bootloader載入才能使用,也就是說,只有JDK內(nèi)部分才能使用這個工廠方法來構(gòu)造Unsafe對象。

1

2

3

4

5

6

7

8

9

10

11

12

13

public final class Unsafe {

    ...

    private Unsafe() {}

    private static final Unsafe theUnsafe = new Unsafe();

    ...

    public static Unsafe getUnsafe() {

       Class cc = sun.reflect.Reflection.getCallerClass(2);

       if (cc.getClassLoader() != null)

           throw new SecurityException("Unsafe");

       return theUnsafe;

    }

    ...

}

幸運地是,有一個theUnsafe屬性可以被利用來檢索Unsafe實例,我們可以見到的寫一個反射方法,來獲取Unsafe實例:

1

2

3

4

5

6

7

public static Unsafe getUnsafe() {

try {

Field f = Unsafe.class.getDeclaredField("theUnsafe");

f.setAccessible(true);

return (Unsafe)f.get(null);

} catch (Exception e) { /* ... */ }

}

下面將學(xué)習(xí)一些Unsafe的方法。

1.long getAddress(long address) void putAddress(long address, long x) 
對直接內(nèi)存進(jìn)行讀寫。

2.int getInt(Object o, long offset) , void putInt(Object o, long offset, int x)

另一個類似的方法對直接內(nèi)存進(jìn)行讀寫,將C語言的結(jié)構(gòu)體和Java對象進(jìn)行轉(zhuǎn)換。

3.long allocateMemory(long bytes)

這個可以看做是C語言的malloc()函數(shù)的一種包裝。

sizeof()函數(shù)

Java對象的結(jié)構(gòu)如下圖所示:

第一個技巧,是模擬C語言的sizefo()函數(shù),這個函數(shù)返回對象的字節(jié)大小。我們可以用如下的代碼實現(xiàn)sizeof()函數(shù):

1

2

3

4

5

6

7

8

9

public static long sizeOf(Object object) {

   Unsafe unsafe = getUnsafe();

   return unsafe.getAddress( normalize( unsafe.getInt(object, 4L) ) + 12L );

}

 

public static long normalize(int value) {

   if(value >= 0) return value;

   return (~0L >>> 32) & value;

}

我們需要使用normalize()函數(shù),因為如果內(nèi)存地址如果在2^31和2^32之間,將會自動的覆蓋鄰近的整型,也就是說用補(bǔ)碼的方式進(jìn)行存儲。讓我們在32位JVM(JDK6或者7)中進(jìn)行測試:

1

2

3

4

5

// 執(zhí)行sizeOf(new MyStructure())得到如下的結(jié)果:

 

class MyStructure { } // 8: 4 (起始標(biāo)記) + 4 (指向類的指針)

class MyStructure { int x; } // 16: 4 (起始標(biāo)記) + 4 (指向類的指針) + 4 (int) + 4 填充字節(jié)用來對齊64位塊

class MyStructure { int x; int y; } // 16: 4 (起始標(biāo)記) + 4 (指向類的指針) + 2*4

直接內(nèi)存管理

Unsafe允許通過allcateMemory和freeMemory方法對內(nèi)存進(jìn)行顯示的分配和回收,直接分配的內(nèi)存不在GC的控制內(nèi),并且不受限于JVM堆的大小。通常,通過NIO的脫離堆約束的緩沖,這些方法是安全有效的,但是有趣的是這讓標(biāo)準(zhǔn)的Java引用映射非堆內(nèi)存變成了可能:

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

MyStructure structure = new MyStructure(); // create a test object

structure.x = 777;

 

long size = sizeOf(structure);

long offheapPointer = getUnsafe().allocateMemory(size);

getUnsafe().copyMemory(

                structure,      // source object

                0,              // source offset is zero - copy an entire object

                null,           // destination is specified by absolute address, so destination object is null

                offheapPointer, // destination address

                size

); // test object was copied to off-heap

 

Pointer p = new Pointer(); // Pointer is just a handler that stores address of some object

long pointerOffset = getUnsafe().objectFieldOffset(Pointer.class.getDeclaredField("pointer"));

getUnsafe().putLong(p, pointerOffset, offheapPointer); // set pointer to off-heap copy of the test object

 

structure.x = 222; // rewrite x value in the original object

System.out.println(  ((MyStructure)p.pointer).x  ); // prints 777

 

....

 

class Pointer {

    Object pointer;

}

所以,事實上是可以對真實對象進(jìn)行內(nèi)存分配和回收的,不單單只是NIO中的字節(jié)緩沖。當(dāng)然,有一個比較大的問題是,GC將會在這樣的內(nèi)存欺騙之后發(fā)生。

繼承自Final類和void*

想象一下有一個以String為參數(shù)的方法,但它需要經(jīng)行外部的重載。具體代碼如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

Carrier carrier = new Carrier();

carrier.secret = 777;

 

String message = (String)(Object)carrier; // ClassCastException

handler( message );

 

...

 

void handler(String message) {

   System.out.println( ((Carrier)(Object)message).secret );

}

 

...

 

class Carrier {

   int secret;

}

為了讓這段代碼能工作,首先需要更改Carrier類去偽裝成String的子類。superclasses列表被存儲在Carrier類結(jié)構(gòu)體28的位置,如上文圖中所示。原則上,添加如下的代碼可以讓Carrer轉(zhuǎn)化成String:

1

2

3

long carrierClassAddress = normalize( unsafe.getInt(carrier, 4L) );

long stringClassAddress = normalize( unsafe.getInt("", 4L) );

unsafe.putAddress(carrierClassAddress + 32, stringClassAddress); // insert pointer to String class to the list of Carrier's superclasses

這樣,類型轉(zhuǎn)化可以正常工作。然而,這樣的轉(zhuǎn)換方式是不切當(dāng)并且違反虛擬機(jī)規(guī)范的。更詳細(xì)的方法將包含如下的步驟:

1.在Carrier類中32的位置實際上包含了一個指向Carrier類自己的指針,所以這個指針將被轉(zhuǎn)移到36的位置上,不僅僅是被指針重寫到String類。

2.當(dāng)Carrier繼承自String的時候,String類的final標(biāo)記將被移掉。

sun.misc.Unsafe提供了幾乎是不受限制的監(jiān)控和修改虛擬機(jī)運行時數(shù)據(jù)結(jié)構(gòu)的能力。盡管這些能力幾乎是和Java開發(fā)本身不相干的,但是對于想要學(xué)習(xí)HotSpot虛擬機(jī)但是沒有C++代碼調(diào)試,或者需要去創(chuàng)建特別的分析工具的人來說,Unsafe是一個偉大的工具。

以上就是Java直接內(nèi)存訪問的技巧有哪些,小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降摹OM隳芡ㄟ^這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁標(biāo)題:Java直接內(nèi)存訪問的技巧有哪些
網(wǎng)址分享:http://www.chinadenli.net/article16/iigodg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航手機(jī)網(wǎng)站建設(shè)微信小程序Google品牌網(wǎng)站制作ChatGPT

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)