Unsafe
是Java内部API,外部是禁止调用的,在编译Java类时如果检测到引用了Unsafe
类也会有禁止使用的警告:Unsafe是内部专用 API, 可能会在未来发行版中删除
。sun.misc.Unsafe
代码片段:
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
public final class Unsafe {
private static final Unsafe theUnsafe;
static {
theUnsafe = new Unsafe();
省去其他代码......
}
private Unsafe() {
}
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (var0.getClassLoader() != null) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
省去其他代码......
}
由上代码片段可以看到,Unsafe
类是一个不能被继承的类且不能直接通过new
的方式创建Unsafe
类实例,如果通过getUnsafe
方法获取Unsafe
实例还会检查类加载器,默认只允许Bootstrap Classloader
调用。
既然无法直接通过Unsafe.getUnsafe()
的方式调用,那么可以使用反射的方式去获取Unsafe
类实例。
反射获取Unsafe
类实例代码片段:
// 反射获取Unsafe的theUnsafe成员变量
Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe");
// 反射设置theUnsafe访问权限
theUnsafeField.setAccessible(true);
// 反射获取theUnsafe成员变量值
Unsafe unsafe = (Unsafe) theUnsafeField.get(null);
当然我们也可以用反射创建Unsafe
类实例的方式去获取Unsafe
对象:
// 获取Unsafe无参构造方法
Constructor constructor = Unsafe.class.getDeclaredConstructor();
// 修改构造方法访问权限
constructor.setAccessible(true);
// 反射创建Unsafe类实例,等价于 Unsafe unsafe1 = new Unsafe();
Unsafe unsafe1 = (Unsafe) constructor.newInstance();
获取到了Unsafe
对象我们就可以调用内部的方法了。