zoukankan      html  css  js  c++  java
  • Unsafe类

    一、Unsafe类仅能被BootstrapClassLoader加载的类实例化,用户建的类默认都是ApplicationClassLoader加载的,实例化Unsafe时会报错(可直接管理内存,不对用户开放使用)。可以用反射实例化(方式一)。补充:加启动参数指定当前类由BootstrapClassLoader加载(方式二)

        private Unsafe() {//构造方法私有化,与下面static构造单例
        }
    
        @CallerSensitive
        public static Unsafe getUnsafe() {
            Class var0 = Reflection.getCallerClass();
            if (!VM.isSystemDomainLoader(var0.getClassLoader())) {//判断是否BootstrapClassLoader加载的类执行实例化的
                throw new SecurityException("Unsafe");
            } else {
                return theUnsafe;
            }
        }
    
        static {
            registerNatives();
            Reflection.registerMethodsToFilter(Unsafe.class, new String[]{"getUnsafe"});
            theUnsafe = new Unsafe();
            ARRAY_BOOLEAN_BASE_OFFSET = theUnsafe.arrayBaseOffset(boolean[].class);
            ARRAY_BYTE_BASE_OFFSET = theUnsafe.arrayBaseOffset(byte[].class);
            ARRAY_SHORT_BASE_OFFSET = theUnsafe.arrayBaseOffset(short[].class);
            ARRAY_CHAR_BASE_OFFSET = theUnsafe.arrayBaseOffset(char[].class);
            ARRAY_INT_BASE_OFFSET = theUnsafe.arrayBaseOffset(int[].class);
            ARRAY_LONG_BASE_OFFSET = theUnsafe.arrayBaseOffset(long[].class);
            ARRAY_FLOAT_BASE_OFFSET = theUnsafe.arrayBaseOffset(float[].class);
            ARRAY_DOUBLE_BASE_OFFSET = theUnsafe.arrayBaseOffset(double[].class);
            ARRAY_OBJECT_BASE_OFFSET = theUnsafe.arrayBaseOffset(Object[].class);
            ARRAY_BOOLEAN_INDEX_SCALE = theUnsafe.arrayIndexScale(boolean[].class);
            ARRAY_BYTE_INDEX_SCALE = theUnsafe.arrayIndexScale(byte[].class);
            ARRAY_SHORT_INDEX_SCALE = theUnsafe.arrayIndexScale(short[].class);
            ARRAY_CHAR_INDEX_SCALE = theUnsafe.arrayIndexScale(char[].class);
            ARRAY_INT_INDEX_SCALE = theUnsafe.arrayIndexScale(int[].class);
            ARRAY_LONG_INDEX_SCALE = theUnsafe.arrayIndexScale(long[].class);
            ARRAY_FLOAT_INDEX_SCALE = theUnsafe.arrayIndexScale(float[].class);
            ARRAY_DOUBLE_INDEX_SCALE = theUnsafe.arrayIndexScale(double[].class);
            ARRAY_OBJECT_INDEX_SCALE = theUnsafe.arrayIndexScale(Object[].class);
            ADDRESS_SIZE = theUnsafe.addressSize();
        }

    二、反射实现实例化

    public class UnsafeTest2 {
        static final Unsafe unsafe;
    
        static final long stateOffset;
    
        private volatile long state = 0;
    
        static {
            try {
                Field field = Unsafe.class.getDeclaredField("theUnsafe");
                field.setAccessible(true);
                unsafe = (Unsafe)field.get(null);//反射得到Unsafe实例
                stateOffset = unsafe.objectFieldOffset(UnsafeTest.class.getDeclaredField("state"));
            }catch (Exception e){
                System.out.println(e.getLocalizedMessage());
                throw new Error(e);
            }
        }
    
        public static void main(String[] args){
            UnsafeTest2 test = new UnsafeTest2();
            Boolean sucess = unsafe.compareAndSwapInt(test,stateOffset,0,1);
            System.out.println(sucess);
        }
    }

    三、重要方法

    long objectFieldOffset(Field field):返回指定的变量在所属类中的内存偏移地址

    int arrayBaseOffset(Class arrayClass):获取数组中第一个元素的地址。

    int arrayIndexScale(Class arrayClass):获取数组中第一个元素占用的字节。

    boolean compareAndSwapLong(Object obj,long offset,long expect,long update):比较对象obj中偏移量为offset的变量的值是否与expect相等,相等则使用update更新,然后返回true,否则返回false。

    public native long getLongvolatile(Object obj,long offset):获取obj对象中偏移量为offset的变量对应的volatile语义的值。

    void putLongvolatile(Object obj,long offset,long value):设置obj对象中offset偏移的类型为long的field的值的value,支持volatile语义(可见性,有序性)

    void putOrderedLong(Object obj,long offset,long value):设置obj对象中offset偏移地址对应的long型field的值为value,无volatile语义(可见性,有序性)

    void park(boolean isAbsolute,long time):阻塞当前线程,其中参数isAbsolute等于false且time等于0时表示一直阻塞

    void unpark(Object thread):唤醒调用park后阻塞的线程。

    long getAndSetLong(Object obj,long offset,long update):获取对象obj中偏移量为offset的变量volatile语义的当前值,并设置变量volatile语义的值为update。

    long getAndAddLong(Object obj,long offset,long addValue):获取对象obj中偏移量为offset的变量volatile语义的当前值,并设置变量的值为原始值+addValue。

    参考自《Java并发编程之美》

  • 相关阅读:
    [转载]Quartus ii 一些Warning/Eeror分析与解决
    [转载]MAC、IP头、TCP头、UDP头帧格式、详解
    [转载]关于晶振ppm
    20140919-FPGA-有效观察设计中的差分信号
    [转载]转一篇Systemverilog的一个牛人总结
    [转载]ISE中COE与MIF文件的联系与区别
    linux系统性能监控--I/O利用率
    linux系统性能监控--内存利用率
    linux系统性能监控--CPU利用率
    在linux系统中I/O 调度的选择
  • 原文地址:https://www.cnblogs.com/wqff-biubiu/p/12154553.html
Copyright © 2011-2022 走看看