yaochow@home:~$

【源码】Unsafe

sun.misc.Unsafe

package sun.misc;

import java.security.*;
import java.lang.reflect.*;

import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;


//看注释,一组执行底层,不安全操作的方法。
/**
 * A collection of methods for performing low-level, unsafe operations.
 * Although the class and all methods are public, use of this class is
 * limited because only trusted code can obtain instances of it.
 *
 * @author John R. Rose
 * @see #getUnsafe
 */

public final class Unsafe {

    //注册本地方法
    private static native void registerNatives();
    static {
        registerNatives();
        sun.reflect.Reflection.registerMethodsToFilter(Unsafe.class, "getUnsafe");
    }

    //不能通过new Unsafe()来实例化。
    private Unsafe() {}

    //单例
    private static final Unsafe theUnsafe = new Unsafe();

    /**
     * 此方法被限制只有Bootstrap Class Loader加载的类才能调用,要不然会抛出SecurityException异常。
     *
     * 1.可以通过反射来获取Unsafe实例。
     * Unsafe.class.getDeclaredField("theUnsafe");
     * f.setAccessible(true);
     * Unsafe unsafe = (Unsafe) f.get(null);
     *
     * 2.可以令使用到Unsafe的类授信
     * java -Xbootclasspath: com.local.test.xxx
     */
    @CallerSensitive
    public static Unsafe getUnsafe() {
        Class<?> caller = Reflection.getCallerClass();
        if (!VM.isSystemDomainLoader(caller.getClassLoader()))
            throw new SecurityException("Unsafe");
        return theUnsafe;
    }

    //通过对象偏移量获取值(这个值可以是8大基本类型,也可以是引用类型)。
    //设置对象偏移量的值(这个值可以是8大基本类型,也可以是引用类型)。
    //每个类型都有独自的上述两种本地方法。
    
    public native int getInt(Object o, long offset);
    public native void putInt(Object o, long offset, int x);
    public native Object getObject(Object o, long offset);
    public native void putObject(Object o, long offset, Object x);
    public native boolean getBoolean(Object o, long offset);
    public native void    putBoolean(Object o, long offset, boolean x);
    public native byte    getByte(Object o, long offset);
    public native void    putByte(Object o, long offset, byte x);
    public native short   getShort(Object o, long offset);
    public native void    putShort(Object o, long offset, short x);
    public native char    getChar(Object o, long offset);
    public native void    putChar(Object o, long offset, char x);
    public native long    getLong(Object o, long offset);
    public native void    putLong(Object o, long offset, long x);
    public native float   getFloat(Object o, long offset);
    public native void    putFloat(Object o, long offset, float x);
    public native double  getDouble(Object o, long offset);
    public native void    putDouble(Object o, long offset, double x);

    @Deprecated
    public int getInt(Object o, int offset) {
        return getInt(o, (long)offset);
    }
    @Deprecated
    public void putInt(Object o, int offset, int x) {
        putInt(o, (long)offset, x);
    }
    @Deprecated
    public Object getObject(Object o, int offset) {
        return getObject(o, (long)offset);
    }
    @Deprecated
    public void putObject(Object o, int offset, Object x) {
        putObject(o, (long)offset, x);
    }
    @Deprecated
    public boolean getBoolean(Object o, int offset) {
        return getBoolean(o, (long)offset);
    }
    @Deprecated
    public void putBoolean(Object o, int offset, boolean x) {
        putBoolean(o, (long)offset, x);
    }
    @Deprecated
    public byte getByte(Object o, int offset) {
        return getByte(o, (long)offset);
    }
    @Deprecated
    public void putByte(Object o, int offset, byte x) {
        putByte(o, (long)offset, x);
    }
    @Deprecated
    public short getShort(Object o, int offset) {
        return getShort(o, (long)offset);
    }
    @Deprecated
    public void putShort(Object o, int offset, short x) {
        putShort(o, (long)offset, x);
    }
    @Deprecated
    public char getChar(Object o, int offset) {
        return getChar(o, (long)offset);
    }
    @Deprecated
    public void putChar(Object o, int offset, char x) {
        putChar(o, (long)offset, x);
    }
    @Deprecated
    public long getLong(Object o, int offset) {
        return getLong(o, (long)offset);
    }
    @Deprecated
    public void putLong(Object o, int offset, long x) {
        putLong(o, (long)offset, x);
    }
    @Deprecated
    public float getFloat(Object o, int offset) {
        return getFloat(o, (long)offset);
    }
    @Deprecated
    public void putFloat(Object o, int offset, float x) {
        putFloat(o, (long)offset, x);
    }
    @Deprecated
    public double getDouble(Object o, int offset) {
        return getDouble(o, (long)offset);
    }
    @Deprecated
    public void putDouble(Object o, int offset, double x) {
        putDouble(o, (long)offset, x);
    }

  
    //获取给定地址的值(这个值可以是8大基本类型,也可以是引用类型)。
    //设置给定地址上的值(这个值可以是8大基本类型,也可以是引用类型)。
    //每个类型都有独自的上述两种本地方法。
    
    public native byte    getByte(long address);
    public native void    putByte(long address, byte x);
    public native short   getShort(long address);
    public native void    putShort(long address, short x);
    public native char    getChar(long address);
    public native void    putChar(long address, char x);
    public native int     getInt(long address);
    public native void    putInt(long address, int x);
    public native long    getLong(long address);
    public native void    putLong(long address, long x);
    public native float   getFloat(long address);
    public native void    putFloat(long address, float x);
    public native double  getDouble(long address);
    public native void    putDouble(long address, double x);

    //获取给定地址的本地指针
    //设置给定地址的本地指针
    public native long getAddress(long address);
    public native void putAddress(long address, long x);

    /// wrappers for malloc, realloc, free:

    //分配内存
    public native long allocateMemory(long bytes);
    //重新分配内存
    public native long reallocateMemory(long address, long bytes);

    //初始化内存内容
    public native void setMemory(Object o, long offset, long bytes, byte value);
    public void setMemory(long address, long bytes, byte value) {
        setMemory(null, address, bytes, value);
    }

    //拷贝内存内容
    public native void copyMemory(Object srcBase, long srcOffset,
                                  Object destBase, long destOffset,
                                  long bytes);
    public void copyMemory(long srcAddress, long destAddress, long bytes) {
        copyMemory(null, srcAddress, null, destAddress, bytes);
    }

   //释放内存
    public native void freeMemory(long address);

    /// random queries

    /**
     * This constant differs from all results that will ever be returned from
     * {@link #staticFieldOffset}, {@link #objectFieldOffset},
     * or {@link #arrayBaseOffset}.
     */
    public static final int INVALID_FIELD_OFFSET   = -1;

   
    @Deprecated
    public int fieldOffset(Field f) {
        if (Modifier.isStatic(f.getModifiers()))
            return (int) staticFieldOffset(f);
        else
            return (int) objectFieldOffset(f);
    }
    @Deprecated
    public Object staticFieldBase(Class<?> c) {
        Field[] fields = c.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            if (Modifier.isStatic(fields[i].getModifiers())) {
                return staticFieldBase(fields[i]);
            }
        }
        return null;
    }

    //获取静态属性偏移量
    public native long staticFieldOffset(Field f);

    //获取对象字段的偏移量
    public native long objectFieldOffset(Field f);

    //返回静态属性的位置,实际上这个方法返回的是一个快照,有可能返回null,它是一个‘cookie’而不是一个对象。
    public native Object staticFieldBase(Field f);

    //检查给定的class是否需要初始化
    public native boolean shouldBeInitialized(Class<?> c);

    //检查给定的class是否已经初始化
    public native void ensureClassInitialized(Class<?> c);

    //返回数组第一个元素的偏移量
    public native int arrayBaseOffset(Class<?> arrayClass);

    public static final int ARRAY_BOOLEAN_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(boolean[].class);

    public static final int ARRAY_BYTE_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(byte[].class);

    public static final int ARRAY_SHORT_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(short[].class);

    public static final int ARRAY_CHAR_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(char[].class);

    public static final int ARRAY_INT_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(int[].class);

    public static final int ARRAY_LONG_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(long[].class);

    public static final int ARRAY_FLOAT_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(float[].class);

    public static final int ARRAY_DOUBLE_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(double[].class);

    public static final int ARRAY_OBJECT_BASE_OFFSET
            = theUnsafe.arrayBaseOffset(Object[].class);

    //返回数组中元素的偏移量
    public native int arrayIndexScale(Class<?> arrayClass);

    public static final int ARRAY_BOOLEAN_INDEX_SCALE
            = theUnsafe.arrayIndexScale(boolean[].class);

    public static final int ARRAY_BYTE_INDEX_SCALE
            = theUnsafe.arrayIndexScale(byte[].class);

    public static final int ARRAY_SHORT_INDEX_SCALE
            = theUnsafe.arrayIndexScale(short[].class);

    public static final int ARRAY_CHAR_INDEX_SCALE
            = theUnsafe.arrayIndexScale(char[].class);

    public static final int ARRAY_INT_INDEX_SCALE
            = theUnsafe.arrayIndexScale(int[].class);

    public static final int ARRAY_LONG_INDEX_SCALE
            = theUnsafe.arrayIndexScale(long[].class);

    public static final int ARRAY_FLOAT_INDEX_SCALE
            = theUnsafe.arrayIndexScale(float[].class);

    public static final int ARRAY_DOUBLE_INDEX_SCALE
            = theUnsafe.arrayIndexScale(double[].class);

    public static final int ARRAY_OBJECT_INDEX_SCALE
            = theUnsafe.arrayIndexScale(Object[].class);

    //获取本地指针大小(byte),通常为4or8
    public native int addressSize();

    public static final int ADDRESS_SIZE = theUnsafe.addressSize();

    //获取本地内存的页数,2的幂次方。
    public native int pageSize();

	//定义一个类,跳过JVM所有安全检查
    public native Class<?> defineClass(String name, byte[] b, int off, int len,
                                       ClassLoader loader,
                                       ProtectionDomain protectionDomain);

    //定义一个匿名类。这个匿名类不是Java层面上的匿名类,
    //Java层面上的匿名内部类在VM中还是正常的,有名字的类(名字是由Java源码编译器(例如javac)构造出来的)。
    public native Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches);


    //创建一个对象但不会执行任何构造器,如果没有初始化进行初始化。
    public native Object allocateInstance(Class<?> cls)
        throws InstantiationException;

    //锁定对象,必须通过monitorExit来解锁;可重入,需要monitorExit对应解锁。
    public native void monitorEnter(Object o);

    //解锁对象,前提是对象被monitorEnter锁了。否则抛出IllegalMonitorStateException。
    public native void monitorExit(Object o);

    //常识锁定对象,如果成功返回true否则false;需要monitorExit解锁。
    public native boolean tryMonitorEnter(Object o);

    //绕过检测机制直接抛出异常。
    public native void throwException(Throwable ee);


    //对于对象引用o,原子性更新offset偏移量属性值为x,当且仅当原值是expected时操作成功返回true。
    public final native boolean compareAndSwapObject(Object o, long offset,
                                                     Object expected,
                                                     Object x);

    //同上
    public final native boolean compareAndSwapInt(Object o, long offset,
                                                  int expected,
                                                  int x);

    //同上
    public final native boolean compareAndSwapLong(Object o, long offset,
                                                   long expected,
                                                   long x);

    //从主内存中获取对象值,要求被使用的属性被volatile修饰,要不然和getObject功能一样。
    public native Object getObjectVolatile(Object o, long offset);

    //设置对象值,直接更新到主内存,保证对其他线程是可见的。
    public native void    putObjectVolatile(Object o, long offset, Object x);
    public native int     getIntVolatile(Object o, long offset);
    public native void    putIntVolatile(Object o, long offset, int x);
    public native boolean getBooleanVolatile(Object o, long offset);
    public native void    putBooleanVolatile(Object o, long offset, boolean x);
    public native byte    getByteVolatile(Object o, long offset);
    public native void    putByteVolatile(Object o, long offset, byte x);
    public native short   getShortVolatile(Object o, long offset);
    public native void    putShortVolatile(Object o, long offset, short x);
    public native char    getCharVolatile(Object o, long offset);
    public native void    putCharVolatile(Object o, long offset, char x);
    public native long    getLongVolatile(Object o, long offset);
    public native void    putLongVolatile(Object o, long offset, long x);
    public native float   getFloatVolatile(Object o, long offset);
    public native void    putFloatVolatile(Object o, long offset, float x);
    public native double  getDoubleVolatile(Object o, long offset);
    public native void    putDoubleVolatile(Object o, long offset, double x);

    //有序的或者延迟的putObjectVolatile方法,不保证值的改变对其他线程可见。
    public native void    putOrderedObject(Object o, long offset, Object x);
    public native void    putOrderedInt(Object o, long offset, int x);
    public native void    putOrderedLong(Object o, long offset, long x);

    //释放给定park阻塞的线程,也可以解决调用park导致的阻塞。操作不安全,必须保证线程是存活的。
    public native void unpark(Object thread);

    //阻塞当前线程直到unpark被调用,or与其平衡的unpark已经发生,or线程被打断,
    //or阻塞时间超时。
    public native void park(boolean isAbsolute, long time);

    //获取系统的平均负载值,loadavg这个double数组将会存放负载值的结果,nelems决定样本数量,
    //nelems只能取值为1到3,分别代表最近1、5、15分钟内系统的平均负载。
    //如果无法获取系统的负载,此方法返回-1,否则返回获取到的样本数量(loadavg中有效的元素个数)。
    public native int getLoadAverage(double[] loadavg, int nelems);

    //CAS操作
    public final int getAndAddInt(Object o, long offset, int delta) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!compareAndSwapInt(o, offset, v, v + delta));
        return v;
    }

    public final long getAndAddLong(Object o, long offset, long delta) {
        long v;
        do {
            v = getLongVolatile(o, offset);
        } while (!compareAndSwapLong(o, offset, v, v + delta));
        return v;
    }
    
    public final int getAndSetInt(Object o, long offset, int newValue) {
        int v;
        do {
            v = getIntVolatile(o, offset);
        } while (!compareAndSwapInt(o, offset, v, newValue));
        return v;
    }

    public final long getAndSetLong(Object o, long offset, long newValue) {
        long v;
        do {
            v = getLongVolatile(o, offset);
        } while (!compareAndSwapLong(o, offset, v, newValue));
        return v;
    }

    public final Object getAndSetObject(Object o, long offset, Object newValue) {
        Object v;
        do {
            v = getObjectVolatile(o, offset);
        } while (!compareAndSwapObject(o, offset, v, newValue));
        return v;
    }


    //方法前的所有读操作一定在屏障前完成,since 1.8
    public native void loadFence();

    //方法前的所有写操作一定在屏障前完成,since 1.8
    public native void storeFence();

    //方法前的所有读写操作都在屏障前完成,since 1.8
    public native void fullFence();

    /**
     * Throws IllegalAccessError; for use by the VM.
     * @since 1.8
     */
    private static void throwIllegalAccessError() {
       throw new IllegalAccessError();
    }

}

总结

  1. Unsafe类可以下载openjdk看源码,在目录openjdk\jdk\src\share\classes\sun\misc中。
  2. Java无法直接访问到操作系统底层,而是通过native方法。
  3. Unsafe类提供了硬件级别的原子操作,很多Java的基础类库,包括被广泛使用的高性能开发库都有基于Unsafe类开发,如Netty、Kafka、Akka等。
  4. Unsafe类设计之初只是为了供标准类库使用的,因此不建议在生产环境中使用,【为什么不建议使用?看这里】

源码:openjdk-8u40-src-b25-10_feb_2015