We are now at number six in the Java 9 series: articles looking at some of the JDK Enhancement Proposals (JEPS) hoping to make their way into Java 9. Last week we looked at More Concurrency Updates.

This week we’re looking at JEP 193: Variable Handles. This relates to last week’s Concurrency Updates and looks to define a set of standards for:

  • Invoking the equivalents of java.util.concurrent.atomic and sun.misc.Unsafe operations on object fields and array elements.
  • Fence operations for memory ordering.
  • A reachability fence operation.

Atomic and Unsafe operations

java.util.concurrent.atomic provides a toolkit of classes such as AtomicBoolean, that “support lock-free thread-safe programming on single variables”. Values can be updated without worrying that another thread will update the variable at the same time.

sun.misc.Unsafe facilitates some low level programming, where, for example, a class might need to be created without invoking a constructor. It is only intended to be used by core Java classes. It is famously ‘unsafe’: it is an unsupported API which is not an official standard for Java SE.

JEP 260: Encapsulate Most Internal APIs has caused some controversy – it proposes to make most of the JDK’s internal APIs inaccessible by default. Specifically APIs that were never intended for external use. This has sparked fears about what a post sun.misc.Unsafe would look like. Among other features, sun.misc.Unsafe allowed fenced loads/stores and atomic updates. It compromises some of Java’s safety standards for speed. Any replacement would have to be as fast, if not faster.
However JEP 260 proposes to leave sun.misc.Unsafe accessible due to its critical functionality, and also to gradually provide alternative functionality. There is an awful lot to sun.misc.Unsafe. Some, but not all of the funtionality will be provided by VarHandles.

Variable Handles

A variable gives us a name that refers to storage in memory. A variable handle is a typed reference to a variable. JEP 193 introduces the single abstract class java.lang.invoke.VarHandle: this will allow you to use Java constructs to arrange atomic or ordered operations on fields of individual classes.

Variable handles are represented by a signature polymorphic method: a method that can have a wide range of call signatures and return types. This allows them to support multiple variable types with only one class.

VarHandle intends to abstract the safe access to a memory location. It has methods for atomic operations, and a method descriptor type for each operation. It has a var form that holds a member name for each operation, characterising the method to invoke. The VarHandle API aims to be as least as usable as sun.misc.Unsafe with comparable performance results, and better performance results than Atomic classes.

Using the MethodHandles APIVarHandles are created by looking up the field within the associated class.
For example:

class Foo {
    int i;

    ...
}

...

class Bar {
    static final VarHandle VH_FOO_FIELD_I;

    static {
        try {
            VH_FOO_FIELD_I = MethodHandles.lookup().
                in(Foo.class).
                findVarHandle(Foo.class, "i", int.class);
        } catch (Exception e) {
            throw new Error(e);
        }
    }
}

Code example from JEP 193

Control checks are performed so that an UnsupportedOperationException will be thrown if necessary, for example when trying to invoke the following:

  • Write access mode methods on a final field
  • Numeric-based access mode methods for a reference variable type/ non-numeric (e.g. boolean field

Fenced operations

‘Fenced operations’ are operations that would provide fine-grained control over memory ordering. This is to control the order of things like reads and writes. The JEP discusses a series of fenced operations as being static methods on the new VarHandle class.

The ‘fence’ can be thought of as a temporary protective barrier around the memory. It might be used in a situation where you need to acquire or release the management or a thread safe object.

There will be a minimal viable set of operations to allow for the control of memory ordering.
For example:


   /**
    * Ensures that loads and stores before the fence will not be
    * reordered with loads and stores after the fence.
    *
    * @apiNote Ignoring the many semantic differences from C and
    * C++, this method has memory ordering effects compatible with
    * atomic_thread_fence(memory_order_seq_cst)
    */
   public static void fullFence() {}

   /**
    * Ensures that loads before the fence will not be reordered with
    * loads and stores after the fence.
    *
    * @apiNote Ignoring the many semantic differences from C and
    * C++, this method has memory ordering effects compatible with
    * atomic_thread_fence(memory_order_acquire)
    */
   public static void acquireFence() {}

   /**
    * Ensures that loads and stores before the fence will not be
    * reordered with stores after the fence.
    *
    * @apiNote Ignoring the many semantic differences from C and
    * C++, this method has memory ordering effects compatible with
    * atomic_thread_fence(memory_order_release)
    */
   public static void releaseFence() {}

   /**
    * Ensures that loads before the fence will not be reordered with
    * loads after the fence.
    */
   public static void loadLoadFence() {}

   /**
    * Ensures that stores before the fence will not be reordered with
    * stores after the fence.
    */
   public static void storeStoreFence() {}

Code example from JEP 193

Reachability fence

A reachability fence is a static method on java.lang.ref.Reference – this ensures that the object is not claimable by garbage collection until after the method has been invoked.

 

There is a lot to this JEP, and it needs to be highly performant to replace some of the operations in Unsafe. However so far no major performance issues have been spotted, and at the time of writing the JEP status is ‘completed’.

 

Next up: Encapsulate Most Internal APIs