Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使Java语言拥有了类似C语言指针一样操作内存空间的能力,这无疑也增加了程序发生相关指针问题的风险。在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重。
Unsafe基本都是Native方法构成,为java语言对底层操作提供很大支持(在很多java源码类中都可以看到它的身影如ConcurrentHashMap,AtomicBoolean,LockSupport等类)。
查看Unsafe源码可以发现,Unsafe类使用单例设计模式(通过static只在类加载时初始化实例对象)
Unsafe 提供了获取实例方法(但是条件比较苛刻)
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
//内部会检查该CallerClass是不是由系统类加载器`BootstrapClassLoader`加载 若是则获取Unsafe对象,否则抛出SecurityException异常
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
异常信息:
如果需要安全获取unsafe对象可以通过Java命令行命令-Xbootclasspath/a
把调用Unsafe相关方法的类A所在jar包路径追加到默认的bootstrap路径中,使得A被引导类加载器加载,从而通过Unsafe.getUnsafe
方法安全的获取Unsafe实例。
java -Xbootclasspath/a: ${path} // 其中path为调用Unsafe相关方法的类所在jar包路径
如果在非系统类加载器`BootstrapClassLoader`加载的类中使用Unsafe可以通过反射来获取该类实例对象
//获取Unsafe 第一个字段属性 其实就是Unsafe实例对象
Field field =Unsafe.class.getDeclaredFields()[0];
field.setAccessible(true);
//获取实例对象
Unsafe unsafe = (Unsafe)field.get(null);
Unsafe类获取对象的方式已然知道了,那么Unsafe具体提供了哪些功能呢?
Java源码中使用到Unsafe类处
:
1:内存管理
DirectByteBuffer是Java用于实现堆外内存(直接内存)的一个重要类,通常用在通信过程中做缓冲池,如在Netty、MINA等NIO框架中应用广泛。DirectByteBuffer对于堆外内存的创建、使用、销毁等逻辑均由Unsafe提供的堆外内存API来实现。
2:CAS
线程安全类AtomicBoolean
3: 线程调度
LockSupport类:
线程挂起:
线程重启:
4:数组操作
AtomicIntegerArray类:
5:内存屏障
StampedLock类:
6:系统管理
java.nio.Bits类 计算待申请内存所需内存页数量的静态方法,其依赖于Unsafe中pageSize方法获取系统内存页大小实现后续计算逻辑,该类在私包中,无法正常初始化