Unsafe

文章目录
  1. 1. Unsafe类
  2. 2. Unsafe操作
Unsafe类
// jdk核心类库可操作的api
public final class Unsafe {
// 对外暴露的实例属性,类加载阶段加载
private static final Unsafe theUnsafe;
static {
...
theUnsafe = new Unsafe();
...
}
private Unsafe() {}

// 该类中的 theUnsafe 属性为该类的一个实例,对外只提供给jdk核心类库使用。我们在平常的开发中无法通过该方法来获取 theUnsafe 对象。(可以通过万能的反射方式获取)
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}

// native方法,阻塞当前线程
public native void park(boolean var1, long var2);

// native方法,唤醒指定的线程
public native void unpark(Object var1);
}

Unsafe操作

获取Unsafe实例

由于Unsafe实例获取方法添加了类加载器验证,所以我们代码中编写的类是无法直接使用Unsafe类的。一般我们可以有两种方式获取Unsafe实例。① 从限制条件入手,修改引导类加载路径,将我们编写的路径添加到引导类路径中。② 通过反射的方式获取。

public static void main(String[] args) throws InterruptedException {
// 获取到Unsafe实例
Unsafe unsafe = getUnsafe();
System.out.println(unsafe);
}

// 1.通过反射获取 Unsafe 实例
private static Unsafe getUnsafe() {
Unsafe unsafe = null;
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe)field.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return unsafe;
}

非常规对象实例化

public static void main(String[] args) throws InterruptedException {
// 非常规对象实例化
People p1 = (People)getInstance(People.class);
People p2 = (People)getInstance(People.class);
System.out.println(p1);
System.out.println(p2);
// 输出结果
// null:0
// null:0
}
// 获取指定类的实例,该方式不会调用指定类的构造方法
public static Object getInstance (Class clazz) {
Unsafe unsafe = getUnsafe();
Object p = null;
try {
p = unsafe.allocateInstance(clazz);
} catch (InstantiationException e) {
e.printStackTrace();
}
return p;
}
// 可操作类
class People {
String name;
int age;

public People(){
this.name = "default";
this.age = 18;
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return this.name + ":" + this.age;
}
}

多线程同步(CAS操作)

juc提供了一些原子操作类,这些类中使用了 Unsafe 类中提供的一些方法。

public class AtomicInteger extends Number implements java.io.Serializable {
// 获取到 Unsafe 类对象
private static final Unsafe unsafe = Unsafe.getUnsafe();
// value属性在内存地址中的偏移量
private static final long valueOffset;
// 静态代码块,初始化 valueOffset 属性
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 该类所持有的值
private volatile int value;

// 获取当前值,并将其加1
// 调用 UnSafe 类的 getAndAddInt 方法,返回 this 对象上地址偏移量为 valueOffset 处的值,并将其加1
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
}

public final class Unsafe {
...
// 某个对象的某个地址偏移处的值加上某个值,并将原始值返回
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
// 获取到原始值
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
// 获取
public native int getIntVolatile(Object var1, long var2);
// CAS更新
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
...
}

挂起与恢复

LockSupport中提供了两个方法,parkunpark方法,而这两个方法实际上又是调用的Unsafe类中的native方法。park是将当前调用线程阻塞,而unpark方法则是唤醒指定的线程。

public class LockSupport {
// 加载 Unsafe 类型的 UNSAFE 实例
private static final sun.misc.Unsafe UNSAFE;
static {
try {
...
UNSAFE = sun.misc.Unsafe.getUnsafe();
...
} catch (Exception ex) { throw new Error(ex); }
}

// LockSupport提供了挂起当前线程的多个方法
public static void park() {
UNSAFE.park(false, 0L);
}

public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}

// 调用 Unsafe 类的unpark方法唤醒指定的线程
public static void unpark(Thread thread) {
if (thread != null) {
UNSAFE.unpark(thread);
}
}
}


public final class Unsafe {
...
// 操作系统底层提供的挂起线程的方法(阻塞线程)
public native void park(boolean var1, long var2);
// 操作系统底层提供的唤醒线程的方法(取消阻塞线程)
public native void unpark(Object var1);
// 几个过期的方法
// 获得对象锁(可重入锁)
@Deprecated
public native void monitorEnter(Object var1);
// 释放对象锁
@Deprecated
public native void monitorExit(Object var1);
// 尝试获取对象锁
@Deprecated
public native boolean tryMonitorEnter(Object var1);
...
}

内存管理

// 内存分配
public native long allocateMemory(long var1);
// 扩充内存
public native long reallocateMemory(long var1, long var3);
// 释放内存
public native void freeMemory(long var1);
// 在给定的内存块中设置值
public native void setMemory(Object var1, long var2, long var4, byte var6);
// 内存拷贝
public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);

// 关于堆外内存的使用
// 使用原因: 垃圾回收停顿的改善 提升程序IO操作的性能
// java实现堆外内存操作的类 DirectByteBuffer
class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer {

}

数组操作


内存屏障