我花了很多时间研究Java 9的一些新功能,但我没有找到任何有用和实用的例子.
考虑下一个创建VarHandle的代码片段:
class Counter {
int i;
}
class VarHandleInAction {
static final VarHandle VH_COUNTER_FIELD_I;
static {
try {
VH_COUNTER_FIELD_I = MethodHandles.lookup().
in(Counter.class).
findVarHandle(Counter.class, "i", int.class);
} catch (Exception e) {
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
但下一步是什么?我的意思是,如何使用这个可变句柄?你能提供任何真实的例子吗?
Jor*_*nee 32
例如,它用于AtomicReference以前使用Java 8的地方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);
}
Run Code Online (Sandbox Code Playgroud)
这里this指针与字段偏移一起使用以访问字段.但这是不安全的,因为这个字段偏移可能是任何long,你实际上可能正在访问完全不同的东西.但是以这种方式实现性能优势(它告诉VM使用专门的CPU指令),并且因为其他人已经使用过,sun.misc.Unsafe即使它是一个内部的,不安全的 API.
VarHandles的部分目的是sun.misc.Unsafe用安全的等价物替换操作.JEP中说明了这一点:
定义一个标准方法来调用各种java.util.concurrent.atomic和sun.misc.Unsafe操作的等价物......
目标:
以下是必修目标:
安全.必须无法将Java虚拟机置于损坏的内存状态.例如,对象的字段只能使用可转换为字段类型的实例进行更新,或者只有在数组索引位于数组边界内时才能在数组中访问数组元素.
诚信.除了无法更新对象的最终字段的约束之外,对对象字段的访问遵循与getfield和putfield字节代码相同的访问规则.(注意:此类安全性和完整性规则也适用于MethodHandles,允许对字段进行读取或写入访问.)
性能.性能特征必须与等效的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);
}
Run Code Online (Sandbox Code Playgroud)
这样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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4404 次 |
| 最近记录: |