例如,它用于 ,而以前在 Java 8 中使用:AtomicReference
sun.misc.Unsafe
public final void lazySet(V newValue) {
unsafe.putOrderedObject(this, valueOffset, newValue);
}
public final boolean compareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
}
此处,指针与字段偏移量一起使用以访问字段。但这是不安全的,因为此字段偏移量可以是任何 ,并且您实际上可能正在访问完全不同的东西。然而,这样做有性能优势(例如,它告诉VM使用专门的CPU指令),并且由于其他人已经使用过,即使它是一个内部的,不安全的API。this
long
sun.misc.Unsafe
的部分目的是将 中的操作替换为安全的等效项。这在 JEP 中指出:VarHandle
sun.misc.Unsafe
定义一个标准方法来调用各种java.util.concurrent.atomic和sun.misc.Unsafe操作的等效项...
目标:
以下是必需的目标:
-
安全。一定不可能将 Java 虚拟机置于损坏的内存状态。例如,对象的字段只能使用可强制转换为字段类型的实例进行更新,或者如果数组索引在数组边界内,则只能在数组内访问数组元素。
-
正直。对对象字段的访问遵循与 getfield 和 putfield 字节码相同的访问规则,此外还有无法更新对象的最终字段的约束。(注意:此类安全和完整性规则也适用于授予对字段的读取或写入访问权限的方法处理程序。
-
性能。性能特征必须与等效的 sun.misc.Unsafe 操作相同或相似(具体而言,生成的汇编程序代码应与某些无法折叠的安全检查模数几乎相同)。
-
可用性。该 API 必须优于 sun.misc.Unsafe API。
所以在Java 9中,这些方法看起来像这样:
public final void lazySet(V newValue) {
VALUE.setRelease(this, newValue);
}
public final boolean compareAndSet(V expectedValue, V newValue) {
return VALUE.compareAndSet(this, expectedValue, newValue);
}
其中有如下定义:VALUE
VarHandle
private static final VarHandle VALUE;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class);
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}