当前位置:首页 > IT科技类资讯

Java中Unsafe使用详解

Unsafe介绍

Unsafe是用详位于sun.misc包下的一个类,主要提供一些用于执行低级别、用详不安全操作的用详方法,如直接访问系统内存资源、用详自主管理内存资源等,用详这些方法在提升Java运行效率、用详增强Java语言底层资源操作能力方面起到了很大的用详作用。但由于Unsafe类使得Java语言拥有了类似C语言指针一样操作内存空间的用详能力,这无疑也增加了程序发生相关指针问题的用详风险。在程序中过度、用详不正确使用Unsafe类会使得程序出错的用详概率变大,使得Java这种安全的用详语言变得不再“安全”,因此对Unsafe的用详使用一定要慎重。云南idc服务商

java.util.concurrent.atomic包下的用详原子操作类,基本都是用详使用Unsafe实现的。

Unsafe提供的API大致可分为内存操作、CAS、Class、对象操作、线程、系统信息获取、内存屏障、数组操作等几类。

内存相关

CAS相关

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类中有应用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); } 

Class相关

对象操作相关

系统相关

内存屏障

loadFence:保证在这个屏障之前的所有读操作都已经完成。

storeFence:保证在这个屏障之前的所有写操作都已经完成。高防服务器

fullFence:保证在这个屏障之前的所有读写操作都已经完成。

在java8中 有这个StampedLock类,该类中应用了内存屏障功能。

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实例

Unsafe类是final且是单例的,并且theUnsafe字段是private;通过如下方法获取实例

方法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();     } } 

Unsafe简单应用

int i = 0 ; public static void main(String[] args) throws Exception {      UnsafeDemo d = new UnsafeDemo() ;     // 获取Unsafe实例     Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe") ;     theUnsafe.setAccessible(true) ;     Unsafe unsafe = (Unsafe) theUnsafe.get(null) ;     // 获取类的实例变量     Field f = UnsafeDemo.class.getDeclaredField("i") ;     // 获取字段相对Java对象的"起始地址"的偏移量     long fieldOffset = unsafe.objectFieldOffset(f) ;     System.out.println(fieldOffset) ;     // 设置值     boolean success = unsafe.compareAndSwapInt(d, fieldOffset, 0, 10) ;     System.out.println(success) ;     System.out.println(d.i) ; } 

Unsafe对象操作

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();     } } 

执行结果:

对象操作2:

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()) ; } 

Unsafe创建对象

当不知道即将使用的对象有何构造函数,或是不想使用现有对象的构造函数创建对象时,可以通过如下方式:

Constructor<Teacher> cons = (Constructor<Teacher>) ReflectionFactory.getReflectionFactory().newConstructorForSerialization(Teacher.class,                 Object.class.getConstructor()); cons.setAccessible(true); Teacher t = cons.newInstance() ; System.out.println(t) ; 

Unsafe简单实现原子操作类

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);     } } 

完毕!!!

服务器托管

分享到:

滇ICP备2023006006号-16