API review of VarHandles
Aleksey Shipilev
aleksey.shipilev at oracle.com
Fri Jan 22 13:06:09 UTC 2016
On 01/22/2016 03:08 PM, Vitaly Davidovich wrote:
> The VarHandle API isn't ergonomic like Unsafe; this being for power users
> is irrelevant to the ergonomics of the API. Instead, it's fairly verbose
> with setup ceremony. Now, I personally don't mind that too much and more
> interested in the features it provides but I'm not surprised by David's
> reaction.
Um, I don't get the "fairly verbose" and "setup ceremony" parts,
especially in comparison with Unsafe. Unsafe also comes with a setup
ceremony, don't you think?
See:
public class C {
static class CU {
static final Unsafe U;
static final long OFFSET;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
U = (Unsafe) f.get(null);
OFFSET = U.objectFieldOffset(CU.class.getDeclaredField("x"));
} catch (ReflectiveOperationException eh) {
throw new IllegalStateException(eh);
}
}
private int x;
public boolean doCas(int expected, int value) {
return U.compareAndSwapInt(this, OFFSET, expected, value);
}
}
static class VU {
static final VarHandle VH;
static {
try {
VH = MethodHandles.lookup().findVarHandle(
VU.class, "x", int.class);
} catch (ReflectiveOperationException eh) {
throw new IllegalStateException(eh);
}
}
private int x;
public boolean doCas(int expected, int value) {
return VH.compareAndSet(this, expected, value);
}
}
}
Even if you pull off Unsafe lookup into separate "holder" class, you'd
still need to lookup OFFSET.
Granted, VH lookup requires learning new stuff, but so does Unsafe,
A*FU, Reflection, or any other special API/syntax. The mind trick is
that you already *know* all those APIs, and so they appear conceptually
simple to you. Once you internalize that VarHandle is a "handle", which
you have to acquire before use, it clicks.
> People already provide nicer APIs on top of Unsafe in their own projects,
> and I suspect this will be even more so with VH.
Yes, but lacking the syntax support, that's the best you can do:
static class MyAwesomeWrapper {
public static VarHandle iAmPrettySureThatFieldExists(
MethodHandles.Lookup lookup, Class<?> recv, String name,
Class<?> type) {
try {
return lookup.findVarHandle(recv, name, type);
} catch (ReflectiveOperationException eh) {
throw new IllegalStateException(eh);
}
}
}
static class VUH {
static final VarHandle VH =
MyAwesomeWrapper.iAmPrettySureThatFieldExists(
MethodHandles.lookup(),
VUH.class, "x", int.class);
private int x;
public boolean doCas(int expected, int value) {
return VH.compareAndSet(this, expected, value);
}
}
...which is not that bad?
I am not discounting David's comments about the conceptual complexity of
the documentation. It looks like a normative text that 99% users would
not read, but stroll straight into code examples.
-Aleksey
More information about the core-libs-dev
mailing list