I have been spending much time investigating some of Java 9's new features, but I didn't find any useful and practical examples.
Consider next code snippet that creates a 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) { // ... } } }
But what's next? I mean, how to use this Variable Handle? Can you provide any real examples?
A VarHandle is a dynamically strongly typed reference to a variable, or to a parametrically-defined family of variables, including static fields, non-static fields, array elements, or components of an off-heap data structure.
Variable Handle is a variable or reference to a set of variables, including other components of a static field, non-static fields, and outer array elements in the heap data structure. It means that Variable Handle is similar to the existing Method Handle. It can be represented by using java. lang.
It is used for instance in AtomicReference
, where previously in Java 8, sun.misc.Unsafe
was used:
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); }
Here the this
pointer is used together with a field offset to access the field. But this is unsafe, since this field offset could be any long
, and you might actually be accessing something completely different. There are however performance benefits in doing it this way (it tells the VM to use specialized CPU instructions for instance), and because of that other people have used sun.misc.Unsafe
even though it's an internal, and unsafe API.
Part of the purpose for VarHandle
s is to replace operations in sun.misc.Unsafe
with a safe equivalent. Which is stated in the JEP:
Define a standard means to invoke the equivalents of various java.util.concurrent.atomic and sun.misc.Unsafe operations...
Goals:
The following are required goals:
Safety. It must not be possible to place the Java Virtual Machine in a corrupt memory state. For example, a field of an object can only be updated with instances that are castable to the field type, or an array element can only be accessed within an array if the array index is within the array bounds.
Integrity. Access to a field of an object follows the same access rules as with getfield and putfield byte codes in addition to the constraint that a final field of an object cannot be updated. (Note: such safety and integrity rules also apply to MethodHandles giving read or write access to a field.)
Performance. The performance characteristics must be the same as or similar to equivalent sun.misc.Unsafe operations (specifically, generated assembler code should be almost identical modulo certain safety checks that cannot be folded away).
Usability. The API must be better than the sun.misc.Unsafe API.
So in Java 9 these methods look like this:
public final void lazySet(V newValue) { VALUE.setRelease(this, newValue); } public final boolean compareAndSet(V expectedValue, V newValue) { return VALUE.compareAndSet(this, expectedValue, newValue); }
Where VALUE
is a VarHandle
define like this:
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); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With