您好,登錄后才能下訂單哦!
Java中Unsafe如何使用,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。
Unsafe是位于sun.misc包下的一個(gè)類,主要提供一些用于執(zhí)行低級(jí)別、不安全操作的方法,如直接訪問(wèn)系統(tǒng)內(nèi)存資源、自主管理內(nèi)存資源等,這些方法在提升Java運(yùn)行效率、增強(qiáng)Java語(yǔ)言底層資源操作能力方面起到了很大的作用。但由于Unsafe類使得Java語(yǔ)言擁有了類似C語(yǔ)言指針一樣操作內(nèi)存空間的能力,這無(wú)疑也增加了程序發(fā)生相關(guān)指針問(wèn)題的風(fēng)險(xiǎn)。在程序中過(guò)度、不正確使用Unsafe類會(huì)使得程序出錯(cuò)的概率變大,使得Java這種安全的語(yǔ)言變得不再“安全”,因此對(duì)Unsafe的使用一定要慎重。
java.util.concurrent.atomic包下的原子操作類,基本都是使用Unsafe實(shí)現(xiàn)的。
Unsafe提供的API大致可分為內(nèi)存操作、CAS、Class、對(duì)象操作、線程、系統(tǒng)信息獲取、內(nèi)存屏障、數(shù)組操作等幾類。
java.util.concurrent.atomic包中的原子類基本都用的Unsafe
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; static { try { valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } public final int getAndSet(int newValue) { return unsafe.getAndSetInt(this, valueOffset, newValue); }
LockSupport類中有應(yīng)用unpark,park
public static void park(Object blocker) { Thread t = Thread.currentThread(); setBlocker(t, blocker); UNSAFE.park(false, 0L); setBlocker(t, null); }
public static void unpark(Thread thread) { if (thread != null) UNSAFE.unpark(thread); }
loadFence:保證在這個(gè)屏障之前的所有讀操作都已經(jīng)完成。
storeFence:保證在這個(gè)屏障之前的所有寫(xiě)操作都已經(jīng)完成。
fullFence:保證在這個(gè)屏障之前的所有讀寫(xiě)操作都已經(jīng)完成。
在java8中 有這個(gè)StampedLock類,該類中應(yīng)用了內(nèi)存屏障功能。
private static final sun.misc.Unsafe U; static { try { U = sun.misc.Unsafe.getUnsafe(); } catch (Exception e) { throw new Error(e); } } public boolean validate(long stamp) { U.loadFence(); return (stamp & SBITS) == (state & SBITS); }
U.loadFence();
Unsafe.java
public final class Unsafe { private static native void registerNatives(); static { registerNatives(); sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe"); } private Unsafe() {} private static final Unsafe theUnsafe = new Unsafe(); // ... }
Unsafe類是final且是單例的,并且theUnsafe字段是private;通過(guò)如下方法獲取實(shí)例
方法1
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; theUnsafe.setAccessible(true) ; Unsafe unsafe = (Unsafe) theUnsafe.get(null) ;
方法2
private static Unsafe unsafe = null ; static { try { Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ; cons.setAccessible(true) ; unsafe = cons.newInstance() ; } catch (Exception e) { e.printStackTrace(); } }
int i = 0 ; public static void main(String[] args) throws Exception { UnsafeDemo d = new UnsafeDemo() ; // 獲取Unsafe實(shí)例 Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; theUnsafe.setAccessible(true) ; Unsafe unsafe = (Unsafe) theUnsafe.get(null) ; // 獲取類的實(shí)例變量 Field f = UnsafeDemo.class.getDeclaredField("i") ; // 獲取字段相對(duì)Java對(duì)象的"起始地址"的偏移量 long fieldOffset = unsafe.objectFieldOffset(f) ; System.out.println(fieldOffset) ; // 設(shè)置值 boolean success = unsafe.compareAndSwapInt(d, fieldOffset, 0, 10) ; System.out.println(success) ; System.out.println(d.i) ; }
private static Unsafe unsafe = null ; static { try { Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor() ; cons.setAccessible(true) ; unsafe = cons.newInstance() ; } catch (Exception e) { e.printStackTrace(); } } public static void allocate() { try { Person p = (Person)unsafe.allocateInstance(Person.class) ; p.setId("s001"); System.out.println(p.getValue()) ; System.out.println(p.getId()) ; } catch (Exception e) { e.printStackTrace(); } }
執(zhí)行結(jié)果:
private Person p = new Person("1", "張三") ; public static void main(String[] args) throws Exception { UnSafeObjectDemo d = new UnSafeObjectDemo() ; Field field = Unsafe.class.getDeclaredField("theUnsafe") ; field.setAccessible(true) ; Unsafe unsafe = (Unsafe) field.get(null) ; Field f = d.getClass().getDeclaredField("p") ; long offset = unsafe.objectFieldOffset(f) ; System.out.println(offset) ; boolean res = unsafe.compareAndSwapObject(d, offset, d.p, new Person("2", "李四")) ; System.out.println(res) ; System.out.println(d.p.getName()) ; }
當(dāng)不知道即將使用的對(duì)象有何構(gòu)造函數(shù),或是不想使用現(xiàn)有對(duì)象的構(gòu)造函數(shù)創(chuàng)建對(duì)象時(shí),可以通過(guò)如下方式:
Constructor<Teacher> cons = (Constructor<Teacher>) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(Teacher.class, Object.class.getConstructor()); cons.setAccessible(true); Teacher t = cons.newInstance() ; System.out.println(t) ;
public class AtomicCount { private static Unsafe unsafe ; private int value ; private static long valueOffset ; static { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ; theUnsafe.setAccessible(true) ; unsafe = (Unsafe) theUnsafe.get(null) ; Field f = AtomicCount.class.getDeclaredField("value") ; valueOffset = unsafe.objectFieldOffset(f) ; } catch (Exception e) { e.printStackTrace(); } } public AtomicCount(int value) { this.value = value ; } public final int get() { return value; } public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } }
關(guān)于Java中Unsafe如何使用問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。