sun.misc.Unsafe简介
1 概要
sun.misc.Unsafe是JDK提供的用于很底层编程的类,位于sun.misc包中。在有些底层编程的场景,Java语言层面办不到的事情,我们可能需要使用JNI,借助C语言去实现。但是使用JNI并不是唯一的选择,使用JNI会将代码绑定到特定的平台,使用Unsafe类可以保留Java语言代码对平台的独立性,又实现底层编程。
2 获取Unsafe类的实例
Unsafe类并没有public的构造函数,只提供了一个静态工厂方法,这个静态方法还只提供给JDK标准库自身的类调用,在我们自己随便建的一个普通的类调用这个静态工厂方法还会抛异常。
这个静态工厂方法的代码如下:
@CallerSensitive
public static Unsafe getUnsafe() {
Class<?> caller = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(caller.getClassLoader()))
throw new SecurityException("Unsafe");
return theUnsafe;
}
可以看到,这个方法对调用者做了判断,一般的调用者调用这个方法会抛异常。
我们做个实验,编写如下代码:
import sun.misc.Unsafe;
public class TestUnsafe {
public static Unsafe getUnsafe() {
return Unsafe.getUnsafe();
}
public static void main(String[] args) {
getUnsafe();
}
}
编译后执行,可以看到程序抛出异常:
zk@zk-mbp:~ » java TestUnsafe
Exception in thread "main" java.lang.SecurityException: Unsafe
at jdk.unsupported/sun.misc.Unsafe.getUnsafe(Unsafe.java:100)
at TestUnsafe.getUnsafe(TestUnsafe.java:6)
at TestUnsafe.main(TestUnsafe.java:10)
那么如何得到Unsafe实例呢?可以使用反射的方式。
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class TestUnsafe {
private static Unsafe unsafe;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
unsafe = (Unsafe) f.get(null);
} catch (Exception e) {
//
}
}
}
下文将在上面的类的基础上实现几个测试Unsafe的方法。
3 使用Unsafe实例化类
看如下一个非常简单的类:
class Num {
private int value;
public Num() {
this.value = 1;
}
public int getValue() {
return this.value
}
}
一个简单的Num类,有一个私有的int类型的value属性,它有get方法,没有set方法,在唯一的构造函数中给value赋值为1
毫无疑问,使用new实例的方式,实例化一个Num,它的value将会是1
Num num = new Num();
assertEquals(num.getValue(), 1);
使用Unsafe类的**allocateInstance()**方法,可以实现只为Num类在堆上分配内存,而不调用其构造方法:
public static void allocateInstanceTest() throws InstantiationException {
Num num = (Num) unsafe.allocateInstance(Num.class);
System.out.println(num.getV