Unsafe是位于sun.misc包下的一个类,主要提供一些用于执行低级别、不安全操作的方法,如直接访问系统内存资源、自主管理内存资源等,这些方法在提升Java运行效率、增强Java语言底层资源操作能力方面起到了很大的作用。
Unsafe的单例实现:
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
当且仅当调用getUnsafe方法的类为引导类加载器所加载时才合法,否则抛出SecurityException异常。
可以通过反射的方式获得theUnsafe。
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
// 将字段的访问权限设置为true
f.setAccessible(true);
// 因为theUnsafe字段在Unsafe类中是一个静态字段,所以通过Field.get()获取字段值时,可以传null获取
Unsafe unsafe = (Unsafe) f.get(null);
Author author = (Author) unsafe.allocateInstance(Author.class) ;
Field ageField = Author.class.getDeclaredField("age") ;
long fieldOffset = unsafe.objectFieldOffset(ageField) ;
String[] strings = new String[]{"1","2","3"} ;
// 返回数组中第一个元素在内存中的偏移量
long i = unsafe.arrayBaseOffset(String[].class) ;
long address = unsafe.allocateMemory(8L) ;
log.info("address:"+address);
}catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}catch (InstantiationException e) {
e.printStackTrace();
}
Unsafe主要提供的功能如下:
内存操作
典型应用:DirectByteBuffe,提供堆外内存的缓冲池,为NIO框架广泛使用。
CAS操作
典型应用java.util.concurrent.atomic相关类,保证原子操作,支持多线程并发
线程操作
Java锁和同步器框架的核心类AbstractQueuedSynchronizer,就是通过调用LockSupport.park()和LockSupport.unpark()实现线程的阻塞和唤醒的
class类操作
从Java 8开始,JDK使用invokedynamic及VM Anonymous Class结合来实现Java语言层面上的Lambda表达式。
对象操作
Unsafe中提供allocateInstance方法,仅通过Class对象就可以创建此类的实例对象,而且不需要调用其构造函数、初始化代码、JVM安全检查等。在Gson反序列化时,如果类有默认构造函数,则通过反射调用默认构造函数创建实例,否则通过UnsafeAllocator来实现对象实例的构造
数组操作
java.util.concurrent.atomic 包下的AtomicIntegerArray(可以实现对Integer数组中每个元素的原子性操作)中有典型的应用,如下图AtomicIntegerArray源码所示,通过Unsafe的arrayBaseOffset、arrayIndexScale分别获取数组首元素的偏移地址base及单个元素大小因子scale。
内存屏障
在Java 8中引入了一种锁的新机制——StampedLock,它可以看成是读写锁的一个改进版本。StampedLock提供了一种乐观读锁的实现
系统相关
如下图所示的代码片段,为java.nio下的工具类Bits中计算待申请内存所需内存页数量的静态方法,其依赖于Unsafe中pageSize方法获取系统内存页大小实现后续计算逻辑。
更多更详细的说明以及典型使用查看美团技术写的https://www.toutiao.com/a6657827547260125700/
更多unsafe的API说明可以参考:https://blog.csdn.net/qq_34436819/article/details/102723579