多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
下面是Unsafe的主要功能: * 普通读写:读写一个Object的field;直接从内存地址读写 * volatile读写:volatile读写Object的field,可以保证可见性和有序性 * 有序写:有序写Object的field,保证有序性不保证可见性 * 直接内存操作:申请内存;重新申请内存;释放内存;内存复制 * CAS相关:提供int,long,和Object的CAS操作 * 偏移量相关:获取对象属性和静态属性的偏移量;获取数组的arrayBaseOffset和arrayIndexScale * 线程调度:挂起线程,唤醒线程,monitorEnter,monitorExit * 类加载:定义类,创建对象,定义匿名内部类,确保一个类被加载,判断是否加载一个类 * 内存屏障:读屏障,写屏障,读写屏障 * [1 获取Unsafe实例](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#1_Unsafe_14) * [2 普通读写](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#2__25) * [3 volatile读写](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#3_volatile_96) * [4 有序写](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#4__103) * [5 直接内存操作](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#5__109) * [6 compareAndSwap相关](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#6_compareAndSwap_118) * [7 偏移量相关](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#7__242) * [8 线程调度](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#8__251) * [9 类加载](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#9__262) * [10 内存屏障](https://www.kancloud.cn/book/zhaoxuyang/blog/fc815341991a4bf102a30860315fff449c706ec3/preview/%E7%90%86%E8%A7%A3Unsafe.md#10__276) ## 1 获取Unsafe实例 通过反射获取Unsafe实例: ~~~ public static Unsafe getUnsafe() throws IllegalAccessException { Field unsafeField = Unsafe.class.getDeclaredFields()[0]; unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); return unsafe; } ~~~ ## 2 普通读写 ~~~ // 读写一个Object属性的相关方法 public native int getInt(Object o, long l); public native void putInt(Object o, long l, int i); // 读写内存地址属性的相关方法 public native int getInt(long l); public native void putInt(long l, int i); ~~~ 下面是测试用例: ~~~ package sun.misc; import java.lang.reflect.Field; /** * * @author zhaoxuyang */ public class UnsafeTest { public static void main(String[] args) throws IllegalAccessException, NoSuchFieldException { Model m = new Model(1, "zhangsan", 22); sun.misc.Unsafe unsafe = getUnsafe(); System.out.println(unsafe.toString()); Class<?> c = Model.class; long idOffset = unsafe.objectFieldOffset(c.getDeclaredField("id")); long nameOffset = unsafe.objectFieldOffset(c.getDeclaredField("name")); long ageOffset = unsafe.objectFieldOffset(c.getDeclaredField("age")); System.out.println("idOffset: " + idOffset); System.out.println("nameOffset: " + nameOffset); System.out.println("ageOffset: " + ageOffset); // 读写一个Object属性的相关方法 int getIntId = unsafe.getInt(m, idOffset); int getIntName = unsafe.getInt(m, nameOffset); int getIntAge = unsafe.getInt(m, ageOffset); System.out.println(getIntId); System.out.println(getIntName); System.out.println(getIntAge); unsafe.putInt(m, ageOffset, getIntAge + 1); System.out.println(m.age); } public static Unsafe getUnsafe() throws IllegalAccessException { Field unsafeField = Unsafe.class.getDeclaredFields()[0]; unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); return unsafe; } private static class Model { long id; String name; int age; Model(long id, String name, int age) { this.id = id; this.name = name; this.age = age; } } } ~~~ ## 3 volatile读写 ~~~ // 普通的读写无法保证可见性和有序性,而volatile读写就可以保证可见性和有序性。 public native int getIntVolatile(Object o, long l); public native void putIntVolatile(Object o, long l, int i); ~~~ ## 4 有序写 ~~~ // 有序写入只保证写入的有序性,不保证可见性,即一个线程的写入不保证其他线程立马可见,但是效率比volatile高。 public native void putOrderedInt(Object o, long l, int i); ~~~ ## 5 直接内存操作 ~~~ public native long allocateMemory(long l); // 分配内存 public native long reallocateMemory(long l, long l1); // 重新分配内存 public native void setMemory(Object o, long l, long l1, byte b); // 内存初始化 public native void copyMemory(Object o, long l, Object o1, long l1, long l2); // 内存复制 public native void freeMemory(long l); // 清除内存 ~~~ ## 6 compareAndSwap相关 Unsafe中提供了int,long和Object的CAS操作: ~~~ public final native boolean compareAndSwapObject(Object o, long l, Object o1, Object o2); public final native boolean compareAndSwapInt(Object o, long l, int i, int i1); public final native boolean compareAndSwapLong(Object o, long l, long l1, long l2); ~~~ CAS示例如下: ~~~ package sun.misc; import java.lang.reflect.Field; /** * * @author zhaoxuyang */ public class CasDemo{ private volatile int value; private static final long valueOffset; private final static Unsafe unsafe; static { try { unsafe = getUnsafe(); valueOffset = unsafe.objectFieldOffset(CasDemo.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } } private static Unsafe getUnsafe() throws IllegalAccessException { Field unsafeField = Unsafe.class.getDeclaredFields()[0]; unsafeField.setAccessible(true); Unsafe unsafe = (Unsafe) unsafeField.get(null); return unsafe; } public final boolean cas(int expect, int update){ return unsafe.compareAndSwapInt(this, valueOffset, expect, update); } public final int getAndIncr(){ return unsafe.getAndAddInt(this, valueOffset, 1); } public final int getAndDecr(){ return unsafe.getAndAddInt(this, valueOffset, -1); } public final int getValue(){ return value; } } ~~~ 下面的例子将实现两个线程交替打印奇偶数: ~~~ package sun.misc; /** * * @author zhaoxuyang */ public class CasDemoTest { public static void main(String[] args) throws InterruptedException { CasDemo casDemo = new CasDemo(); System.out.println(casDemo.getValue()); Thread t1 = new Thread(() -> { while(true){ int value = casDemo.getValue(); if(value > 10){ break; } if(value % 2 == 1){ System.out.println("线程1 " + value); casDemo.cas(value, value + 1); } } }); Thread t2 = new Thread(() -> { while(true){ int value = casDemo.getValue(); if(value > 10){ break; } if(value % 2 == 0){ System.out.println("线程2 " + value); casDemo.cas(value, value + 1); } } }); t1.start(); t2.start(); Thread.sleep(200); System.out.println(casDemo.getValue()); } } ~~~ 输出如下: ~~~ run: 0 线程2 0 线程1 1 线程2 2 线程1 3 线程2 4 线程1 5 线程2 6 线程1 7 线程2 8 线程1 9 线程2 10 11 ~~~ ## 7 偏移量相关 ~~~ public native long staticFieldOffset(Field field); // 获取静态属性Field在对象中的偏移量 public native long objectFieldOffset(Field field); // 非静态属性Field在对象实例中的偏移量 public native Object staticFieldBase(Field field); // 返回Field所在的对象 public native int arrayBaseOffset(Class<?> type); // 返回数组中第一个元素实际地址相对数组地址的偏移量 public native int arrayIndexScale(Class<?> type); //计算数组中第一个元素所占用的内存空间 ~~~ ## 8 线程调度 ~~~ public native void park(boolean bln, long l); // 挂起线程 public native void unpark(Object o); // 唤醒线程 // 用于加锁,synchronized便是通过以下指令实现 @Deprecated public native void monitorEnter(Object o); @Deprecated public native void monitorExit(Object o); @Deprecated public native boolean tryMonitorEnter(Object o); ~~~ ## 9 类加载 ~~~ // 定义一个类,用于动态地创建类 public native Class<?> defineClass(String string, byte[] bytes, int i, int i1, ClassLoader cl, ProtectionDomain pd); // 用于动态地创建一个匿名内部类 public native Class<?> defineAnonymousClass(Class<?> type, byte[] bytes, Object[] os); // 用于创建一个类的实例,但是不会调用这个实例的构造方法,如果这个类还未被初始化,则初始化这个类。 public native Object allocateInstance(Class<?> type) throws InstantiationException; // 用于判断是否需要初始化一个类 public native boolean shouldBeInitialized(Class<?> type); // 用于保证已经初始化过一个类 public native void ensureClassInitialized(Class<?> type); ~~~ ## 10 内存屏障 ~~~ public native void loadFence(); // 保证在这个屏障之前的所有【读】操作都已经完成 public native void storeFence(); // 【写】 public native void fullFence(); // 【读写】 ~~~