下面是Unsafe的主要功能:

  • 普通读写:读写一个Object的field;直接从内存地址读写
  • volatile读写:volatile读写Object的field,可以保证可见性和有序性
  • 有序写:有序写Object的field,保证有序性不保证可见性
  • 直接内存操作:申请内存;重新申请内存;释放内存;内存复制
  • CAS相关:提供int,long,和Object的CAS操作
  • 偏移量相关:获取对象属性和静态属性的偏移量;获取数组的arrayBaseOffset和arrayIndexScale
  • 线程调度:挂起线程,唤醒线程,monitorEnter,monitorExit
  • 类加载:定义类,创建对象,定义匿名内部类,确保一个类被加载,判断是否加载一个类
  • 内存屏障:读屏障,写屏障,读写屏障

获取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;
}

普通读写

// 读写一个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;
        }
    }
}

volatile读写

// 普通的读写无法保证可见性和有序性,而volatile读写就可以保证可见性和有序性。
public native int getIntVolatile(Object o, long l);
public native void putIntVolatile(Object o, long l, int i);

有序写

// 有序写入只保证写入的有序性,不保证可见性,即一个线程的写入不保证其他线程立马可见,但是效率比volatile高。
public native void putOrderedInt(Object o, long l, int i);

直接内存操作

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);  // 清除内存

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

偏移量相关

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); //计算数组中第一个元素所占用的内存空间

线程调度

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); 

类加载

// 定义一个类,用于动态地创建类
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);

内存屏障

public native void loadFence(); // 保证在这个屏障之前的所有【读】操作都已经完成
public native void storeFence(); // 【写】
public native void fullFence();  // 【读写】