Unsafe阅读笔记:
一、基本描述
-
final类,单例 且 不可集成。
-
实例化类:Unsafe类使用了单例模式,需要通过一个静态方法getUnsafe()来获取。但Unsafe类做了限制,如果是普通的调用的话,它会抛出一个SecurityException异常;只有由主类加载器加载的类才能调用这个方法
-
//Java反射实例化Unsafe类 public Unsafe getUnsafe() throws IllegalAccessException { //Field unsafeField = Unsafe.class.getDeclaredFields()[0]; Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); // 将字段的访问权限设置为true unsafeField.setAccessible(true); // 因为theUnsafe字段在Unsafe类中是一个静态字段,所以通过Field.get()获取字段值时,可以传null获取 Unsafe unsafe = (Unsafe) unsafeField.get(null); return unsafe; }
-
二、详细介绍
1、先看一张图,参考里面有什么功能,毕竟是工具类嘛
2、然后根据上面的图来分析工具类的函数
-
普通读写:读写一个Object对象的field;直接从内存中的一个地址读写。
-
public native int getInt(Object var1, long var2);
- 从对象指定偏移地址处读取一个int
-
public native void putInt(Object var1, long var2, int var4);
- 从IG对象指定偏移地址写入一个int值
-
public native byte getByte(long var1);
- 从指定内存地址获取一个byte
-
public native void putByte(long var1, byte var3);
- 在指定内存地址写入一个byte
-
volatile读写:volatile读写一个Object的field,volatile可以保证可见性和有序性。
-
public native void putObjectVolatile(Object var1, long var2, Object var4);
- 在对象指定偏移地址写入一个object,保证有序和可见
-
public native int getIntVolatile(Object var1, long var2);
- 在对象指定偏移地址使用volatile读取一个int
-
public native void putIntVolatile(Object var1, long var2, int var4);
- 在对象指定偏移地址使用volatile写入一个int ,保证有序和可见
-
-
有序写:有序写一个Object的field,保证有序性不保证可见性,所谓有序性就是保证指令不会被重排。
-
public native void putOrderedObject(Object var1, long var2, Object var4);
- 在对象指定偏移地址写入一个object对象,保证有序性
-
public native void putOrderedInt(Object var1, long var2, int var4);
- 在对象指定偏移地址写入一个int, 保证有序性
-
-
直接内存操作:申请内存,重新申请内存。是释放内存,内存复制。
-
public native long allocateMemory(long var1);
- 分配内存
-
public native long reallocateMemory(long var1, long var3);
- 重新分配内存
-
public native void setMemory(long var1, long var3, byte var5);
- 内存初始化
-
public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);
- 内存复制
-
public native void freeMemory(long var1);
- 清除内存
-
-
CAS相关:提供int,long和object的CAS操作
public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
- (未测试)
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
- (未测试)
public final native boolean compareAndSwapLong(Object var1, long var2, long var4, long var6);
- (未测试)
-
偏移量相关:获取对象属性和静态属性的偏移量;获取数据第一个元素的偏移地址(arrayBaseOffset),元素的增量地址(arrayIndexScale)
public native long staticFieldOffset(Field var1);
- 获取静态属性Field在对象中的偏移量,因为读写静态属性时必须获取其偏移量
public native long objectFieldOffset(Field var1);
- 获取非静态属性Field在对象中的偏移量,因为读写必须获取其偏移量
public native Object staticFieldBase(Field var1);
- 返回静态属性Field所在的对象,必须是对象的静态字段(非静态会报IllegalArgumentException)
public native int arrayBaseOffset(Class<?> var1);
- 返回数组第一个元素实际地址相对整个数组对象的地址的偏移量
public native int arrayIndexScale(Class<?> var1);
- 用于计算数组中第一个元素所占用的内存空间
-
线程调度;挂起线程,唤醒线程,monitorEnter,MonitorExit
-
park(boolean var1, long var2);
- 阻塞线程
-
public native void unpark(Object var1);
- 唤醒线程
-
public native void monitorEnter(Object var1);
- 用于方法加锁(synchronized就是使用的这两个)
-
public native void monitorExit(Object var1);
- (未测试)
-
public native boolean tryMonitorEnter(Object var1);
- (未测试)
-
-
类加载:定义类,创建对象,定义匿名内部类,确保一个类被加载,判断是否加载一个类。
-
public native Class<?> defineClass(String var1, byte[] var2, int var3, int var4, ClassLoader var5, ProtectionDomain var6);
- 定义一个类,用于动态地创建类
-
public native Class<?> defineAnonymousClass(Class<?> var1, byte[] var2, Object[] var3);
- 用于动态的创建一个匿名内部类
-
public native Object allocateInstance(Class<?> var1);
- 实例化对象,但是不进行初始化,类初始化和实例初始化都不调用
-
public native boolean shouldBeInitialized(Class<?> var1);
- 用于判断是否需要初始化一个类(未测试)
-
public native void ensureClassInitialized(Class<?> var1);
- 用于保证已经初始化一个类
-
-
内存屏障:读屏障、写屏障、读写屏障
public native void loadFence();
- 读屏障-禁止load重排序
public native void storeFence();
- 写屏障-禁止store重排序
public native void fullFence();
- 读写屏障-禁止load和store重排序
-
系统相关:提供2个系统的api
public native int addressSize();
- 获得指针的大小(8字节是64位,4字节是32位)
public native int pageSize();
- 返回内存页的大小,单位是字节。返回值一定是2的多少次幂 单位b
以上文章的内容参考:Java中的Unsafe