Variable Handle In Java 9

Variable Handle In Java 9

What Is A Variable Handle?

A Variable Handle or VarHandle is nothing but a typed reference to a variable created in order to provide read and write access to the variable under different access modes. The variables can be array elements, instance or static fields in a class. VarHandle objects cannot be modified once they are created.

Essentially, a varHandle consists of two important parts – a variable type and a list of coordinates. Variable type denotes the type of variable the varHandle gives memory reference to whereas the list of coordinates help to locate the variable whose reference is given by the varHandle.

Why Variable Handles are needed?

Software developers who work on Java-based softwares may feel the need to do low level programming in certain scenarios. Developers of third-party softwares had two ways to do low level programming till Java 8.  They could use JNI to interact with extern functions defined in C. Alternatively, they could also use sun.misc.Unsafe along with Reflection APIs. On first look, using Unsafe seems like a good idea. Unlike JNI, Unsafe doesn’t make the code to be tightly coupled with the underlying OS implemented using C language. But packages under sun.* are not officially supported public APIs by Oracle. As a result, code written using Unsafe might not work on other JDK implementations which does not contain packages defined under sun.*.Therefore, end users are advised not to use it unless the situation really demands.  Furthermore, Oracle had plans to remove these packages from later releases of JDK.

Contributors to JVM specifications created a Java Enhancement Proposal (JEP 193) to address the possible implications. In addition, it also suggests a better and  standardized alternative to perform atomic and unsafe operations on objects and fields of a class. The java.lang.invoke.VarHandle API tries to support most of the operations in sun.misc.Unsafe. This would ensure that nothing is broken while the core development team works on implementation of JEP 260 (Encapsulate Most Internal APIs).

 

Access Modes

Variable Handle has methods that fall into five types of access modes:

  • Read access mode:
    This can be used to get the value of a variable. get(), getVolatile(), getAcquire() and getOpaque() are some methods that support read access.
  • Write access mode:
    This can be used to set the value of a variable. set(), setVolatile(), setRelease() and setOpaque() are some methods that support write access.
  • Atomic update acce0ss mode:
    This can be used to atomically changes the value of the variable after comparing the current and new values. Some of the methods that fall under this category of access mode are: compareAndSet, compareAndExchangeAcquire, compareAndExchange, compareAndExchangeRelease, getAndSet, getAndSetAcquire, getAndSetRelease, etc.
  • Numeric atomic update access mode:
    This can be used in case we want to atomically set value with addition. Methods like getAndAdd, getAndAddAcquire, getAndAddRelease fall under this category.
  • Bitwise atomic update access mode:
    This can be used to retrieve and do a bitwise OR, AND or XOR before setting the value. Some methods that fall under this category are: getAndBitwiseOr, getAndBitwiseOrAcquire, getAndBitwiseOrRelease, getAndBitwiseAnd, getAndBitwiseAndAcquire, getAndBitwiseAndRelease, getAndBitwiseXor, getAndBitwiseXorAcquire, getAndBitwiseXorRelease, etc.

Getting a VarHandle Instance

We can use MethodHandle.lookup()  to create a Variable Handle Instance. A MethodHandle is an executable reference to an underlying method.

Consider the following code.

Create another class in the same package as the MyService class.

The above program will run successfully without throwing an error. But if the variable named id was declared as private in the MyService class, the program would throw UnsupportedOperationException.

VarHandle Of Private Members

We can get a variable handle for a private member using:

Since MethodHandles.privateLookupIn() returns a Lookup object that has a fuller access to the target class’ objects and members, we can obtain the variable handle for the member named id regardless of whether it is private, public or protected.

Previously, Reflection and sun.misc.Unsafe were used together to achieve it. The drawback of the older approach was that setAccessible() sets the value only for a particular instance and does not alter the class properties as such. Sometimes, using setAccessible in code can give undesirable results. Hence VarHandle is a better alternative.

VarHandle For An Array Object

It is possible to get the variable handle for an array using the following code:

After getting the handle for the particular array type, it can be used to do compare and set operations.

Conclusion

Developers of Java language initially created the sun.misc.Unsafe to use it internally in APIs of JVM. But many third party softwares like Hazelcast, JMock, Netty, Hibernate, Spring, etc started using it as it enabled them to do powerful low level operations. The Unsafe API did these operations with better performance than JNI. Critical internal APIs like sun.misc.Unsafe are still available but deprecated in Java 9. They may be eventually encapsulated or removed in Java 10. Therefore, it is a better idea for developers of such softwares to adopt VarHandle API early in their code as an alternative to sun.misc.Unsafe class.

Leave a Reply