zoukankan      html  css  js  c++  java
  • Unsafe使用

    Unsafe

    Unsafe类是JDK底层类库提供的、基于Java内存模型访问底层的机制,通过该类可以实例化对象、直接操作堆外内存(直接内存)、CAS原子操作等。Java基于AQS实现的同步工具类、并发容器,Netty对堆外内存的操作都基于该类实现。

    获取Unsafe实例

    Unsafe中提供了静态方法getUnsafe可以直接获取到Unsafe对象,但是该方法只允许JDK类库调用,我们平时开发中调用该方法将抛出SecurityException异常。

    当然在开发中,我们可以使用反射获取到该类实例。该类中包含一个自身属性Unsafe theUnsafe,通过反射获取该属性即可获取一个初始化后的Unsafe实例。

    Field f = Unsafe.class.getDeclaredField("theUnsafe");
    f.setAccessible(true);
    Unsafe unsafe = (Unsafe) f.get(null);
    

    常用方法

    /**
     * 实例化一个类
     * @param var1 要实例化类的Class对象
     */
    public native Object allocateInstance(Class<?> var1) throws InstantiationException;
    
    /**
     * 获取一个类中某个属性的位移
     * @param var1 属性的Field
     */
    public native long objectFieldOffset(Field var1);
    
    /**
     * 获取某个实例对象的int属性值
     * @param var1 实例对象
     * @param var2 int属性的offset
     */
    public native int getInt(Object var1, long var2);
    
    /**
     * 修改实例对象的int属性值
     * @param var1 实例对象
     * @param var2 int属性的offset
     * @param var4 修改值
     */
    public native void putInt(Object var1, long var2, int var4);
    
    // 省略boolean、byte、char、short、float、double、long、Object
    
    /**
     * 申请堆外内存
     * @param var1 申请内存大小,单位字节
     * @return 堆外内存的起始地址
     */
    public native long allocateMemory(long var1);
    
    /**
     * 释放堆外内存
     * @param var1 堆外内存的起始地址
     */
    public native void freeMemory(long var1);
    
    /**
     * CAS修改实例对象int属性值
     * @param var1 实例对象
     * @param var2 int属性值
     * @param var4 int属性oldVal
     * @param var5 int属性修改值newVal
     */
    public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
    
    // 省略long、Object
    
    /**
     * 唤醒线程
     * 具体使用可以参考 LockSupport.unpark()
     */
    public native void unpark(Object var1);
    
    /**
     * 阻塞线程
     * 具体使用可以参考 LockSupport.park()
     */
    public native void park(boolean var1, long var2);
    
    
    

    代码实例

    public class User {
        private int age = 20;
    
        public static void main(String[] args) {
            // 构造器创建实例
            User user = new User();
            System.out.println(user);
            // age = 20  表明使用构建器创建实例,会初始化实例属性
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
            user.unsafeSetAge(1);
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
    
            user.setAge(2);
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
    
            // unsafe创建实例
            user = User.getInstance();
            System.out.println(user);
            // age = 0  表明使用Unsafe创建实例,并不会初始化实例属性
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
            user.unsafeSetAge(10);
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
    
            // 每次调用都会创建新的实例
            user = User.getInstance();
            System.out.println(user);
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
            user.unsafeSetAge(100);
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
    
            // cas修改
            user.unsafeCas(100, 150);
            System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " +  user.getAge());
    
        }
    
        private static Unsafe UNSAFE;
        private static long AGE_OFFSET;
    
        static {
    
            try {
                Field f = Unsafe.class.getDeclaredField("theUnsafe");
                f.setAccessible(true);
                UNSAFE = (Unsafe) f.get(null);
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    
            try {
                AGE_OFFSET = UNSAFE.objectFieldOffset(User.class.getDeclaredField("age"));
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
    
        public static User getInstance() {
            try {
                return (User)UNSAFE.allocateInstance(User.class);
            } catch (InstantiationException e) {
                e.printStackTrace();
                throw new RuntimeException("初始化User实例失败");
            }
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int unsafeGetAge() {
            return UNSAFE.getInt(this, AGE_OFFSET);
        }
    
        public void unsafeSetAge(int age) {
            UNSAFE.putInt(this, AGE_OFFSET, age);
        }
    
        public void unsafeCas(int expectAge, int newAge) {
            UNSAFE.compareAndSwapInt(this, AGE_OFFSET, expectAge, newAge);
        }
    
        @Override
        public String toString() {
            return "User{" +
                "age=" + age + "," +
                "hashcode=" + this.hashCode() +
                '}';
        }
    }
    
    
  • 相关阅读:
    2、容器初探
    3、二叉树:先序,中序,后序循环遍历详解
    Hebbian Learning Rule
    论文笔记 Weakly-Supervised Spatial Context Networks
    在Caffe添加Python layer详细步骤
    论文笔记 Learning to Compare Image Patches via Convolutional Neural Networks
    Deconvolution 反卷积理解
    论文笔记 Feature Pyramid Networks for Object Detection
    Caffe2 初识
    论文笔记 Densely Connected Convolutional Networks
  • 原文地址:https://www.cnblogs.com/QullLee/p/12241044.html
Copyright © 2011-2022 走看看