<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                java是一個安全性很高的平臺,開發者在使用過程中,并不需要直接對內存進行操作,Unsafe對象字如其名,是一個不安全的工具類,可以突破java語言的限制,對內存進行操作。 ## 初始化 Unsafe的構造方法是私有的,我們不能直接通過new來獲取實例,Unsafe內部有一個靜態方法getUnsafe可以獲取實例; ``` private Unsafe() {} public static Unsafe getUnsafe() { Class cc = sun.reflect.Reflection.getCallerClass(2); if (cc.getClassLoader() != null) //沒有被任何類加載器加載時是null。它會拋出SecurityException 異常 throw new SecurityException("Unsafe"); return theUnsafe; } ``` getUnsafe()方法獲取實例,直接調用時會拋出異常java.lang.SecurityException: Unsafe,只有java認為是安全的代碼才可以加載并獲取Unsafe實例。如此一來,我們編寫的代碼就不能直接通過該方法獲取Unsafe實例了。 不過Unsafe的內部有一個theUnsafe變量,我們可以通過反射來獲取這個實例。獲取實例的方法很簡單,獲取theUnsafe屬性,在調用get方法即可 ``` private static final Unsafe theUnsafe = new Unsafe(); // 通過反射獲取Unsafe實例 public static Unsafe getUnsafe() throws Exception{ Field f = Unsafe.class.getDeclaredField("theUnsafe"); //Internal reference f.setAccessible(true); Unsafe unsafe = (Unsafe) f.get(null); return unsafe; } ``` ## 相關操作 ### 1.分配內存 allocateMemory方法可以用來分配本地內存,下面模擬一個數組UnsafeArray,內部保存byte類型數據;初始化時,根據數組大小分配內存,返回address為數組的基地址,set和get時根據偏移量調用putByte和getByte修改數組內數據。 ``` int BYTESIZE = 1; public UnsafeArray(long size) { address = UNSAFE.allocateMemory(size *BYTESIZE); } public byte get(long index) { return UNSAFE.getByte(address + (index * BYTESIZE)); } public void set(long index,byte result) { UNSAFE.putByte(address + (index * BYTESIZE), result); } ``` ### 2.對象屬性 objectFieldOffset方法可以類的某個屬性在Class中的偏移,根據偏移量調用getInt()和UNFASE.getAndSetInt()可以獲取/設置對象實例該屬性的值。下面以SampleClass類為例,內部有一個整型i默認為5,long型默認為10 ``` public final class SampleClass{ private int i = 5; private long l = 10; private byte[] buf = new byte[4]; } ``` 下面是具體的使用過程 ``` public static void testObject() throws NoSuchFieldException, SecurityException { // 由于對象頭是8+8 int的offset應該是16 long offseti = UNFASE.objectFieldOffset(SampleClass.class.getDeclaredField("i")); System.out.println("offset of i is " + offseti);//offset of i is 12 long offsetl = UNFASE.objectFieldOffset(SampleClass.class.getDeclaredField("l")); System.out.println("offset of l is " + offsetl);//offset of l is 16 SampleClass sampleClass = new SampleClass(); System.out.println("testObject offset of offseti : "+ UNFASE.getInt(sampleClass, offseti));// testObject offset of offseti : 5 System.out.println("testObject offset of offsetl : "+ UNFASE.getInt(sampleClass, offsetl));// testObject offset of offsetl : 10 // UNFASE.getAndSetInt(sampleClass, offseti, 99); System.out.println("sampleClass.getI() = " + sampleClass.getI());// sampleClass.getI() = 99 UNFASE.getAndSetLong(sampleClass, offsetl, 88); System.out.println("sampleClass.getL() = " + sampleClass.getL());// sampleClass.getL() = 88 } ``` ## 3.CAS CAS是java并發包中最常見的無鎖方法,底層均由unsafe實現,有如下方法: ``` /** * 如果對象offset的當前值是expected則更新為x */ public final native boolean compareAndSwapObject(Object o, long offset, Object expected, Object x); public final native boolean compareAndSwapInt(Object o, long offset, int expected, int x); public final native boolean compareAndSwapLong(Object o, long offset, long expected, long x); ``` 在AtomicInteger的源碼中,可以看到cas的使用,其內部使用value記錄了實際的int值,初始化時獲取了value在AtomicInteger的偏移valueOffset,在AtomicInteger提供的方法中,會使用unsafe的相關方法完成cas操作。 ``` //AtomicInteger類源碼 public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); } public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } public final boolean weakCompareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } ``` ## 4.park unsafe有兩個方法park()和unpark()可以用來停止線程和恢復線程,并發包中的很多鎖機制都使用了該方法,下面的例子中會啟動一個線程,休眠5秒或被喚醒后結束;main線程休眠2秒后unpark恢復了內部線程。 ``` Thread thread = new Thread(new Runnable() { public void run() { UNFASE.park(false, TimeUnit.SECONDS.toNanos(5)); System.out.println("innrt thread end"); } }); thread.start(); System.out.println("begin thread!"); TimeUnit.SECONDS.sleep(2); UNFASE.unpark(thread); System.out.println("main thread unpark!"); ``` 打印內容為: ``` 0s-begin thread! 2s-main thread unpark! 2s-innrt thread end ``` ## 5.monitor 臨界區相關的方法有 ``` public native void monitorEnter(Object o); public native void monitorExit(Object o); public native boolean tryMonitorEnter(Object o); ``` 使用方法類似與synchronized類似,進入臨界區之前需要獲得鎖,跳出臨界區后要釋放鎖。park中的例子可以改寫為下面的方式: ``` final Object lock = new Object(); Thread thread = new Thread(new Runnable() { public void run() { UNFASE.monitorEnter(lock); System.out.println("innrt thread end"); } }); thread.start(); UNFASE.monitorEnter(lock); System.out.println("begin thread!"); TimeUnit.SECONDS.sleep(2); UNFASE.monitorExit(lock); System.out.println("main thread unpark!"); ``` # netty對unsafe的使用 netty中在內存相關的操作和cas中使用了unsafe對象,具體程序在PlatformDependent0中。 1.獲取DirectByteBuffer的地址 由于unsafe主要用于分配直接內存,首先獲取了nio的Buffer中是否有address屬性,如果內有則不需要獲取Unsafe對象實例了。 ``` inal ByteBuffer direct = ByteBuffer.allocateDirect(1); ...... final Field field = Buffer.class.getDeclaredField("address"); field.setAccessible(true); // if direct really is a direct buffer, address will be non-zero if (field.getLong(direct) == 0) { return null; } return field; ``` 2. 獲取Unsafe實例,使用反射的方法獲取theUnsafe屬性 3. 大量使用了內存相關的方法
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看