Unsafe使用
Unsafe
Unsafe
类是JDK底层类库提供的、基于Java内存模型访问底层的机制,通过该类可以实例化对象、直接操作堆外内存(直接内存)、CAS原子操作等。Java基于AQS实现的同步工具类、并发容器,Netty对堆外内存的操作都基于该类实现。
获取Unsafe实例
Unsafe
中提供了静态方法getUnsafe
可以直接获取到Unsafe
对象,但是该方法只允许JDK类库调用,我们平时开发中调用该方法将抛出SecurityException
异常。当然在开发中,我们可以使用反射获取到该类实例。该类中包含一个自身属性
Unsafe theUnsafe
,通过反射获取该属性即可获取一个初始化后的Unsafe
实例。
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);
常用方法
/**
* 实例化一个类
* @param var1 要实例化类的Class对象
*/
public native Object allocateInstance(Class<?> var1) throws InstantiationException;
/**
* 获取一个类中某个属性的位移
* @param var1 属性的Field
*/
public native long objectFieldOffset(Field var1);
/**
* 获取某个实例对象的int属性值
* @param var1 实例对象
* @param var2 int属性的offset
*/
public native int getInt(Object var1, long var2);
/**
* 修改实例对象的int属性值
* @param var1 实例对象
* @param var2 int属性的offset
* @param var4 修改值
*/
public native void putInt(Object var1, long var2, int var4);
// 省略boolean、byte、char、short、float、double、long、Object
/**
* 申请堆外内存
* @param var1 申请内存大小,单位字节
* @return 堆外内存的起始地址
*/
public native long allocateMemory(long var1);
/**
* 释放堆外内存
* @param var1 堆外内存的起始地址
*/
public native void freeMemory(long var1);
/**
* CAS修改实例对象int属性值
* @param var1 实例对象
* @param var2 int属性值
* @param var4 int属性oldVal
* @param var5 int属性修改值newVal
*/
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
// 省略long、Object
/**
* 唤醒线程
* 具体使用可以参考 LockSupport.unpark()
*/
public native void unpark(Object var1);
/**
* 阻塞线程
* 具体使用可以参考 LockSupport.park()
*/
public native void park(boolean var1, long var2);
代码实例
public class User {
private int age = 20;
public static void main(String[] args) {
// 构造器创建实例
User user = new User();
System.out.println(user);
// age = 20 表明使用构建器创建实例,会初始化实例属性
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
user.unsafeSetAge(1);
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
user.setAge(2);
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
// unsafe创建实例
user = User.getInstance();
System.out.println(user);
// age = 0 表明使用Unsafe创建实例,并不会初始化实例属性
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
user.unsafeSetAge(10);
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
// 每次调用都会创建新的实例
user = User.getInstance();
System.out.println(user);
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
user.unsafeSetAge(100);
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
// cas修改
user.unsafeCas(100, 150);
System.out.println("unsafeGetAge : " + user.unsafeGetAge() + " userGetAge : " + user.getAge());
}
private static Unsafe UNSAFE;
private static long AGE_OFFSET;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
UNSAFE = (Unsafe) f.get(null);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
try {
AGE_OFFSET = UNSAFE.objectFieldOffset(User.class.getDeclaredField("age"));
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
public static User getInstance() {
try {
return (User)UNSAFE.allocateInstance(User.class);
} catch (InstantiationException e) {
e.printStackTrace();
throw new RuntimeException("初始化User实例失败");
}
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int unsafeGetAge() {
return UNSAFE.getInt(this, AGE_OFFSET);
}
public void unsafeSetAge(int age) {
UNSAFE.putInt(this, AGE_OFFSET, age);
}
public void unsafeCas(int expectAge, int newAge) {
UNSAFE.compareAndSwapInt(this, AGE_OFFSET, expectAge, newAge);
}
@Override
public String toString() {
return "User{" +
"age=" + age + "," +
"hashcode=" + this.hashCode() +
'}';
}
}