Unsafe源码解析
Unsafe类为执行底层的、不安全的操作提供了一个方法的集合。
虽然,这个类的方法都是public
的,但是只有受信任的代码才可以获得这个类的实例。
该类主要使用了单例模式来实现代码,下面我们来看一下主要的源代码。
Unsafe类定义
public final class Unsafe{}
Unsafe类的静态属性
private static final Unsafe theUnsafe = new Unsafe();
private static final int INVALID_FIELD_OFFSET = -1;
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 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);
public static final int ADDRESS_SIZE = theUnsafe.addressSize();
显然,是采用了单例模式的饿汉式方法。
Unsafe类的静态方法
private static native void registerNatives();
@CallerSentitive
public static Unsafe getUnsafe(){
Class<?> caller = Reflection.getCallerClass();
if(!VM.isSystemDomainLoader(caller.getClassLoader())){
throw new SecurityException("Unsafe");
}
return theUnsafe;
}
native方法,是通过JNI的方式调用在JVM中C++语言实现的方法的。
getUnsafe方法,主要是获取Unsafe类的唯一实例,这里采用的单例的设计模式。在该方法中,会校验调用该方法的类的类加载器,只有系统类加载器加载的类才能调用Unsafe的方法。
Unsafe类的构造方法
private Unsafe(){}
Unsafe类对特定对象的get和set操作
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);
上述这些方法主要用于操作Java堆中的对象的属性.
Unsafe中对特定的内存地址的get和set操作
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);
上述方法主要作用于C堆之中,也即所谓的对外内存。
Unsafe中对native指针的get和set操作
public native long getAddress(long address);
public native void putAddress(long address, long x);
getAddress主要是通过给定地址获取一个native指针。
putAddress主要是在给定地址处设置一个native指针。
Unsafe中对内存的操作
public native long allocateMemory(long bytes);
public native long reallocMemory(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);
Unsafe中获取属性的偏移量
public native long staticFieldOffset(Field f);
public native long objectFieldOffset(Field f);
public native long staticFieldBase(Field f);
Unsafe中对类初始化的操作
public native boolean shouldBeInitialized(Class<?> c);
public native void ensureClassInitialized(Class<?> c);
Unsafe中对数组元素偏移量的获取
public native int arrayBaseOffset(Class<?> arrayClass);
Unsafe中对数组元素大小的获取
public native int arrayIndexScale(Class<?> arrayClass);
Unsafe中获取native指针的大小
public native int addressSize();
Unsafe中获取内存页的大小
public native int pageSize();
Unsafe中的类定义方法
public native Class<?> defineClass(String name, byte[] b, int offset, int len, ClassLoader loader, ProtectionDomain protectionDomain);
public native Class<?> defineAnonymousClass(Class<?> hostClass, byte[] data, Object[] cpPatches);
Unsafe中分配实例对象的方法
public native Object allocateInstance(Class<?> cls) throws InstantiationException;
该方法会分配一个类的实例存储空间,但是不会执行构造函数。
Unsafe中的比较设置方法
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);
Unsafe中对Volatile属性的get和set操作
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, long x);
public native boolean getBooleanVolative(Object o, long offset);
public native void putBooleanVolatile(Object o, long offset, boolean 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);
Unsafe中的putOrdered方法
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);
Unsafe中的阻塞/唤醒线程的方法
public native void park(boolean isAbsolute, long time);
public native void unpark(Object thread);
Unsafe中的获取系统平均负载方法
public native int getLoadAverage(double[] loadavg, int nelems);
该方法主要用于获取在各个时间段内分配给可用处理器运行队列的平均负载。该方法会获取由nelems
参数指定的样本数量,并且把样本值赋值给loadavg
数组中的元素。系统最多获取3个样本,分别代表最近1分钟,5分钟和15分钟的平均值。
Unsafe中的内存屏障方法
public native void loadFence();
public native void storeFence();
public native void fullFence();
loadFence:确保在内存屏障之前没有读操作的重排序。
storeFence:确保在内存屏障之前没有写操作的重排序。
fullFence:确保在内存屏障之前没有读或者写操作的重排序。
Unsafe中的抛出异常方法
private static void throwIllegalAccessException(){
throw new IllegalAccessException();
}
主要用于虚拟机中抛出异常
Unsafe中的获取设置方法
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, newValue));
return v;
}
Unsafe中的获取增加方法
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){
int v;
do{
v = getLongVolatile(o, offset);
}while(!compareAndSwapLong(o, offset, v, v + delta));
return v;
}