What is a VarHandle, and why was it introduced as a replacement for sun.misc.Unsafe?
answer
- java.lang.invoke, Java 9, JEP 193
- Typed handle to field / array element / buffer location
- Obtained via MethodHandles.Lookup (access-checked)
- Safe + supported + JIT-fast replacement for sun.misc.Unsafe
- Access modes: plain / opaque / acquire-release / volatile, plus CAS
basics
~20 sA VarHandle (added in Java 9) is a typed reference to a variable — a field, array element, or off-heap location — that lets you read and write it with different levels of atomicity and memory ordering, including CAS. It is the safe, supported, standard replacement for the internal, unsupported sun.misc.Unsafe.
solid answer
~50 sA VarHandle, from java.lang.invoke, is a strongly-typed handle to a variable (an instance/static field, an array element, or a buffer location) obtained via MethodHandles.Lookup. Through it you perform memory operations at a chosen access mode: plain get/set, opaque, acquire/release, and full volatile, plus atomic operations like compareAndSet, getAndAdd, and weakCompareAndSet. It was introduced in Java 9 to give application and library authors a standard, type-checked, JIT-optimized API for the low-level atomic and ordered access that previously was only possible through sun.misc.Unsafe — an internal, unsupported, type-unsafe class that could corrupt memory and that the module system was set to hide. VarHandle delivers the same machine-level performance (it intrinsifies to direct CPU instructions) while enforcing type and access checks, so it is both safe and supported. It is the foundation the atomic classes and field updaters are now built on.
go deeper
Should at least recognize VarHandle as a low-level concurrency API in newer Java; deep usage is not expected.
Can say VarHandle gives atomic/ordered access to fields and arrays and replaced the internal Unsafe, and roughly how you obtain one.
Explains the Unsafe problems (internal, type-unsafe, module-hidden), how VarHandle is type-checked, JIT-intrinsified, obtained via Lookup, and lists the access modes.
Frames the platform motivation (JPMS encapsulating internals, supportability), the performance equivalence via intrinsics, and how VarHandle re-grounds the whole atomic stack on a supported primitive.
## Background: why this API exists To build lock-free data structures and high-performance concurrency primitives, you need low-level control over memory: the ability to perform a **compare-and-swap (CAS)** on a field, to read/write with specific **memory ordering** (controlling when one thread's writes become visible to another), and to do this on fields and array elements directly. For years the JDK's own `Atomic*` classes obtained this power from an internal class, **`sun.misc.Unsafe`**. ### The trouble with sun.misc.Unsafe `sun.misc.Unsafe` is exactly what its name says: a backdoor of raw, unchecked memory operations. - It is **internal and unsupported** — not part of the public Java SE API, with no compatibility guarantee. - It is **type-unsafe**: you pass raw field offsets and object references, and a mistake (wrong offset, wrong type) can corrupt the heap or crash the JVM, because no checks protect you. - It was nonetheless **widely used** by libraries (high-performance queues, serialization frameworks, off-heap stores) because nothing else offered the same capability. - With the **Java Platform Module System (Java 9)**, internal packages like `sun.misc` were to be encapsulated/hidden, threatening to break that ecosystem. The JDK needed a **public, supported, safe** replacement that did not sacrifice performance. That replacement is `VarHandle`. ## What a VarHandle is A **`VarHandle`** (in `java.lang.invoke`, JEP 193, Java 9) is a **typed reference to a variable**. "Variable" here is general: it can be - an **instance field**, - a **static field**, - an **array element**, - or a location in an off-heap buffer (e.g. via `MethodHandles.byteBufferViewVarHandle`). It is the variable-access analogue of a `MethodHandle` (which is a typed reference to a method). You don't read/write the variable directly through the language; you go through the handle, which carries the variable's type and coordinate types (e.g. "this VarHandle accesses an `int` field of receiver type `Node`"). ### How you get one You obtain a VarHandle via a **`MethodHandles.Lookup`**, which enforces access control — you can only get a handle to a variable you are allowed to access: ```java class Counter { private volatile int value; private static final VarHandle VALUE; static { try { VALUE = MethodHandles.lookup() .findVarHandle(Counter.class, "value", int.class); } catch (ReflectiveOperationException e) { throw new ExceptionInInitializerError(e); } } } ``` For arrays you use `MethodHandles.arrayElementVarHandle(int[].class)`, and the access methods then take the array plus the index as coordinates. ## What it lets you do: access modes The defining feature of VarHandle is that **every operation names an access mode** that selects atomicity and memory-ordering strength. The four ordering levels, from weakest to strongest, are: - **plain** (`get`/`set`) — like a normal field read/write, no extra ordering. - **opaque** (`getOpaque`/`setOpaque`) — atomic and coherent per-variable, but no cross-variable ordering. - **acquire/release** (`getAcquire`/`setRelease`) — a release write happens-before a subsequent acquire read of the same variable; one-directional ordering for cheap publication. - **volatile** (`getVolatile`/`setVolatile`) — full volatile semantics (the strongest, bidirectional ordering). On top of those it offers **atomic update** operations: `compareAndSet`, `compareAndExchange`, `weakCompareAndSet` (may fail spuriously, for retry loops), `getAndSet`, `getAndAdd`, `getAndBitwiseOr`, etc. (The access-mode detail is its own topic; the key point here is that one handle exposes the full ladder, where `volatile`/CAS used to be all you could express.) ## Why it is better than Unsafe 1. **Type-safe and access-checked** — the Lookup enforces visibility, and operations are checked against the variable's declared type, so you cannot silently corrupt memory the way a raw offset in Unsafe could. 2. **Supported and standard** — public Java SE API with a compatibility contract, unlike the internal `sun.misc.Unsafe`. 3. **Just as fast** — VarHandle operations are **intrinsified** by the JIT compiler to the same direct CPU instructions Unsafe produced; you get the performance without the danger. 4. **More expressive** — the explicit ladder of access modes lets you choose exactly the ordering strength you need (e.g. cheap acquire/release publication) instead of paying for full `volatile` everywhere. 5. **Module-system friendly** — it is the sanctioned path so libraries can stop depending on encapsulated internals. The JDK rebuilt `AtomicInteger`, `AtomicReference`, the field updaters, and similar primitives on top of VarHandle internally. ## Summary A `VarHandle` is a typed, access-controlled handle to a field/array element/buffer location offering the full ladder of memory-access modes and atomic operations. Java 9 introduced it (JEP 193) as the safe, supported, equally fast, module-friendly replacement for the internal and dangerous `sun.misc.Unsafe`, and it now underpins the atomic classes themselves.
- How do you obtain a VarHandle for a private field, and what enforces that you are allowed to?You use a MethodHandles.Lookup with sufficient access (e.g. MethodHandles.lookup() from inside the declaring class) and call findVarHandle(owner, name, type). The Lookup's access rights enforce visibility, so you cannot get a handle to a field you could not legally access.
- Does VarHandle replace reflection for ordinary field reads/writes?It can read/write fields, but its purpose is low-level atomic/ordered access, not general reflection. It is far faster than reflection (intrinsified, no per-call reflective checks) but is used for concurrency primitives rather than as a general Field replacement.
saying these in an interview costs you the question
- Calling sun.misc.Unsafe a public/supported API — it is internal and unsupported
- Claiming VarHandle is slower than Unsafe — it intrinsifies to the same instructions
- Thinking VarHandle is just reflection — it is JIT-intrinsified, not reflective dispatch per call
- Saying VarHandle only does volatile/CAS — it exposes a full ladder of ordering modes
- Confusing VarHandle (variable access) with MethodHandle (method access)