Java魔法类:Unsafe应用解析
Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。但由于Unsafe类使Java语言拥有了类似C语言指针一样操作内存空间的能力,这无疑也增加了程序发生相关指针问题的风险。在程序中过度、不正确使用Unsafe类会使得程序出错的概率变大,使得Java这种安全的语言变得不再“安全”,因此对Unsafe的使用一定要慎重
。
注:本文对sun.misc.Unsafe公共API功能及相关应用场景进行介绍。基本介绍如下Unsafe源码所示,Unsafe类为一单例实现,提供静态方法getUnsafe获取Unsafe实例,当且仅当调用getUnsafe方法的类为引导类加载器所加载时才合法,否则抛出SecurityException异常。
一:基本介绍
如下Unsafe源码所示,Unsafe类为一单例实现,提供静态方法
getUnsafe
获取Unsafe实例,当且仅当调用getUnsafe方法的类
为引导类加载器
所加载时才合法,否则抛出SecurityException
异常。
public final class Unsafe {
// 单例对象
private static final Unsafe theUnsafe;
private Unsafe() {
}
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
// 仅在引导类加载器`BootstrapClassLoader`加载时才合法
if(!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
}
那如若想使用这个类,该如何获取其实例?有如下两个可行方案。
其一,从
getUnsafe
方法的使用限制条件出发,通过Java命令行命令-Xbootclasspath/a
把调用Unsafe相关方法的类A所在jar包路径追加到默认的bootstrap路径中,使得A被引导类加载器加载,从而通过Unsafe.getUnsafe
方法安全的获取Unsafe实例。java -Xbootclasspath/a: ${path} // 其中path为调用Unsafe相关方法的类所在jar包路径
其二,通过反射获取单例对象
theUnsafe
。private static Unsafe reflectGetUnsafe() { try { // Unsafe类有个成员变量:private static final Unsafe theUnsafe Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); return (Unsafe) field.get(null); } catch (Exception e) { log.error(e.getMessage(), e); return null; } }
或者:先获取
Class对象
,再通过构造器
创建Unsafe对象
// 通过反射获得Unsafe对象 Class unsafeClass = Unsafe.class; // 获得构造函数,Unsafe的构造函数为私有的 Constructor constructor = unsafeClass.getDeclaredConstructor(); // 设置为允许访问私有内容 constructor.setAccessible(true); // 创建Unsafe对象 Unsafe unsafe = (Unsafe) constructor.newInstance();