Mastering Java Unsafe: Low-Level Memory Tricks and Atomic Operations
This article introduces Java's sun.misc.Unsafe class, explains its memory, CAS, thread, class, and object manipulation APIs, shows how to obtain an Unsafe instance, and provides practical code examples for low‑level operations such as field offsets, compare‑and‑swap, object allocation, and custom atomic counters.
Unsafe Introduction
Unsafe is a class in the sun.misc package that provides low‑level, potentially unsafe operations such as direct memory access and manual memory management. While it can improve performance and enable powerful features, misuse can introduce pointer‑like bugs, making Java less safe.
Many classes in java.util.concurrent.atomic are implemented using Unsafe.
Unsafe APIs can be grouped into memory operations, CAS, class manipulation, object manipulation, thread utilities, system information, memory fences, and array operations.
Memory Operations
CAS Operations
Atomic classes in java.util.concurrent.atomic rely on Unsafe.
<code>private static final Unsafe unsafe = Unsafe.getUnsafe();
private static final long valueOffset;
static {
try {
valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
public final int getAndSet(int newValue) {
return unsafe.getAndSetInt(this, valueOffset, newValue);
}
</code>Thread Utilities
LockSupport uses park and unpark which delegate to Unsafe.
<code>public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
public static void unpark(Thread thread) {
if (thread != null)
UNSAFE.unpark(thread);
}
</code>Class Manipulation
Object Operations
System Information
Memory Fences
loadFence : ensures all prior reads are completed. storeFence : ensures all prior writes are completed. fullFence : ensures all prior reads and writes are completed.
Java 8 introduced StampedLock , which uses memory fences.
<code>private static final sun.misc.Unsafe U;
static {
try {
U = sun.misc.Unsafe.getUnsafe();
} catch (Exception e) {
throw new Error(e);
}
}
public boolean validate(long stamp) {
U.loadFence();
return (stamp & SBITS) == (state & SBITS);
}
</code>Obtaining an Unsafe Instance
Unsafe is a final singleton with a private theUnsafe field. Two common ways to get the instance are:
<code>// Method 1
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
// Method 2
private static Unsafe unsafe = null;
static {
try {
Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor();
cons.setAccessible(true);
unsafe = cons.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
</code>Simple Unsafe Usage
<code>int i = 0;
public static void main(String[] args) throws Exception {
UnsafeDemo d = new UnsafeDemo();
// Get Unsafe instance
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
// Get field offset
Field f = UnsafeDemo.class.getDeclaredField("i");
long fieldOffset = unsafe.objectFieldOffset(f);
System.out.println(fieldOffset);
// CAS operation
boolean success = unsafe.compareAndSwapInt(d, fieldOffset, 0, 10);
System.out.println(success);
System.out.println(d.i);
}
</code>Unsafe Object Operations
<code>private static Unsafe unsafe = null;
static {
try {
Constructor<Unsafe> cons = Unsafe.class.getDeclaredConstructor();
cons.setAccessible(true);
unsafe = cons.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void allocate() {
try {
Person p = (Person) unsafe.allocateInstance(Person.class);
p.setId("s001");
System.out.println(p.getValue());
System.out.println(p.getId());
} catch (Exception e) {
e.printStackTrace();
}
}
</code>Result:
Object Operation Example 2
<code>private Person p = new Person("1", "张三");
public static void main(String[] args) throws Exception {
UnSafeObjectDemo d = new UnSafeObjectDemo();
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
Unsafe unsafe = (Unsafe) field.get(null);
Field f = d.getClass().getDeclaredField("p");
long offset = unsafe.objectFieldOffset(f);
System.out.println(offset);
boolean res = unsafe.compareAndSwapObject(d, offset, d.p, new Person("2", "李四"));
System.out.println(res);
System.out.println(d.p.getName());
}
</code>Creating Objects with Unsafe
When the constructor is unknown or you want to bypass it, you can use:
<code>Constructor<Teacher> cons = (Constructor<Teacher>) ReflectionFactory
.getReflectionFactory()
.newConstructorForSerialization(Teacher.class, Object.class.getConstructor());
cons.setAccessible(true);
Teacher t = cons.newInstance();
System.out.println(t);
</code>Simple Atomic Implementation Using Unsafe
<code>public class AtomicCount {
private static Unsafe unsafe;
private int value;
private static long valueOffset;
static {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
unsafe = (Unsafe) theUnsafe.get(null);
Field f = AtomicCount.class.getDeclaredField("value");
valueOffset = unsafe.objectFieldOffset(f);
} catch (Exception e) {
e.printStackTrace();
}
}
public AtomicCount(int value) {
this.value = value;
}
public final int get() {
return value;
}
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
}
</code>End of article.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.