前言
Unsafe是jdk提供操作的增强执行低级别代码和操作底层资源的工具类。jdk1.8及以下的版本在sun.misc包下,jdk11移到jdk.internal.misc包下。sum.misc继续保留,只是实现修改为代理jdk.internal.misc包的实例。下面我们来详细分解以下Unsafe的功能和实现。
使用方法
看Unsafe的源码,我们发现Unsafe类是单例实现的,提供静态方法获取Unsafe实例。
public final class Unsafe {
private static final Unsafe theUnsafe;
private Unsafe() {
}
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}
}
我们在此处看到调用类必须是引导类加载器所加载的类才能调用。否则会抛出SecurityException异常。
即,如果我们的类是引导类加载器所加载的类那么我们就可以直接调用Unsafe的getUnsafe()获取Unsafe的实例。像jdk中java.util.concurrent包的很多并发、原子类一样直接使用:
private static final Unsafe unsafe = Unsafe.getUnsafe();
当时在我们实际开发中我们类,一般不是被引导类加载的,那么这时我们改如何使用呢?
- 第一种:通过-Xbootclasspath、-Xbootclasspath/a 、-Xbootclasspath/p把调用Unsafe的类所在的jar被引导类加载器加载,从而可以直接获得unsafe实例。
- 第二种:通过反射获取单例对象theUnsafe
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
return (Unsafe) field.get(null);
推荐私用第二种方式。也是普遍的用户,如果还有其他方法,欢迎在文章后面留言探讨。
功能介绍
我们先来看一下Unsafe的代码,去除一些功能相似的代码,使用XXX代表不同的类型,简化阅读代码的难度。去除Deprecated标记的过期方法。本代码摘录自openjdk8u分支的jdk/src/share/classes/sun/misc/Unsafe.java。
通过整理分类,我们看到Unsafe主要提供了如下方法给我们使用:管理堆外内存、获取系统相关信息、(类、对象、字段、数组)的相关操作、CAS原子操作、线程相关操作、内存屏障。具体分类的详细方法在下面的源码整理中。
public final class Unsafe {
private static native void registerNatives();
static {
registerNatives(