java的Unsafe类解析

Unsafe性质

  • sun.misc.Unsafe,“后门”类,可以直接操控内存和线程的底层操作,应用于java.nio和并发包等实现
  • Unsafe是final类,不能被继承

-获取Unsafe实例的"唯一"正常手段:
Unsafe unsafe = Unsafe.getUnsafe();

因为有使用限制,看源码就知道了

//构造器私有
private Unsafe() {}

@CallerSensitive
public static Unsafe getUnsafe() {
  Class var0 = Reflection.getCallerClass();
   //只能被Bootloader加载
   if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
     throw new SecurityException("Unsafe");
   } else {
        return theUnsafe;
        }
   }

当然,通过反射也可以获取Unsafe实例:

public static Unsafe getUnsafe() {
   try {
           Field f = Unsafe.class.getDeclaredField("theUnsafe");
           f.setAccessible(true);
           return (Unsafe)f.get(null);
   } catch (Exception e) { 
       /* ... */
   }
}
常用方法

(下文中用到的XXX指参数类型,Unsafe类方法都至少支持三种类型:int、long、object)

注意偏移量都是long类型

  1. objectFieldOffset:获取到指定实例变量(即非静态属性),在对象内存中的偏移量

    因为在别的很多方法中都需要偏移量,所以一般都会先调用这个方法,而且会用常量保留这个偏移量,方便使用。

    // 参数是Field
    public native long objectFieldOffset(Field var1);
    
    所以使用eg:
    long offset = UNSAFE.objectFieldOffset
    (UnsafeTest.class.getDeclaredField("state"));
    

    本方法的object不是指类型为Object,而是指实例变量

    即不存在intFieldOffset、longFieldOffset等方法,别混乱了。

    而获取静态属性的方法就是staticFieldOffset()

    //用法一样,但获取的是静态属性的偏移地址
    public native long staticFieldOffset(Field var1);
    
  2. compareAndSwapXXX:通过比较并替换的机制,修改指定偏移量内存的值

     /**
         * @param var1 对象实例,所以该值经常为 this,指当前实例,值得注意的是数组若为对象类型,那放入数组元素也是可行的
         * @param var2 偏移量
         * @param var4 期望的旧值
         * @param var5 更换的新值
         * @return CAS操作是否成功
    */
    public final native boolean compareAndSwapXXX
        (Object var1, long var2, XXX var4, XXX var5);
    

    compareAndSwapXXX只支持上述三种类型
    在这里插入图片描述

  3. 对volatile变量的get、set方法
    本方法则支持八大基本类型 + object

/**
     * @param var1 对象实例
     * @param var2 偏移量
*/
public native XXX getXXXVolatile(Object var1, long var2);

/**
  * @param var1 对象实例
  * @param var2 偏移量
  * @param var4 需要设置的新值
*/
public native void putXXXVolatile
 (Object var1, long var2, XXX var4);

  1. 其余的getAndSetXXX / getAndAddXXX (也只支持那三个类型)

    也是通过上述方法配合实现

  2. park、unpark方法,用于挂起 / 唤醒某一线程

本文完,若有误欢迎指出。

参考资料:
java中的Unsafe

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值