Skip to content

Commit

Permalink
Remove dependency on sun.misc.Unsafe (#547)
Browse files Browse the repository at this point in the history
This replaces `sun.misc.Unsafe` with
`java.util.concurrent.atomic.AtomicLongFieldUpdater` and
`AtomicIntegerFieldUpdater`. This is to enable compatibility with Jigsaw
modules where `sun.misc.Unsafe` is no longer available.

Closes #468

Signed-off-by: Andre Masella <andre@masella.name>
  • Loading branch information
apmasell committed May 7, 2020
1 parent ac5136b commit fe42313
Showing 1 changed file with 8 additions and 61 deletions.
69 changes: 8 additions & 61 deletions simpleclient/src/main/java/io/prometheus/client/Striped64.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
package io.prometheus.client;

import java.util.Random;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicLongFieldUpdater;

/**
* A package-local class holding common representation and mechanics
Expand Down Expand Up @@ -94,22 +96,10 @@ static final class Cell {
Cell(long x) { value = x; }

final boolean cas(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
return CAS_VALUE.compareAndSet(this, cmp, val);
}

// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long valueOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> ak = Cell.class;
valueOffset = UNSAFE.objectFieldOffset
(ak.getDeclaredField("value"));
} catch (Exception e) {
throw new Error(e);
}
}
private static final AtomicLongFieldUpdater<Cell> CAS_VALUE = AtomicLongFieldUpdater.newUpdater(Cell.class, "value");

}

Expand Down Expand Up @@ -155,14 +145,14 @@ final boolean cas(long cmp, long val) {
* CASes the base field.
*/
final boolean casBase(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val);
return CAS_BASE.compareAndSet(this, cmp, val);
}

/**
* CASes the busy field from 0 to 1 to acquire lock.
*/
final boolean casBusy() {
return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1);
return CAS_BUSY.compareAndSet(this, 0, 1);
}

/**
Expand Down Expand Up @@ -287,50 +277,7 @@ final void internalReset(long initialValue) {
}
}

// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long baseOffset;
private static final long busyOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> sk = Striped64.class;
baseOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("base"));
busyOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("busy"));
} catch (Exception e) {
throw new Error(e);
}
}
private static final AtomicLongFieldUpdater<Striped64> CAS_BASE = AtomicLongFieldUpdater.newUpdater(Striped64.class, "base");
private static final AtomicIntegerFieldUpdater<Striped64> CAS_BUSY = AtomicIntegerFieldUpdater.newUpdater(Striped64.class, "busy");

/**
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
* Replace with a simple call to Unsafe.getUnsafe when integrating
* into a jdk.
*
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
try {
return sun.misc.Unsafe.getUnsafe();
} catch (SecurityException tryReflectionInstead) {}
try {
return java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
public sun.misc.Unsafe run() throws Exception {
Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
for (java.lang.reflect.Field f : k.getDeclaredFields()) {
f.setAccessible(true);
Object x = f.get(null);
if (k.isInstance(x))
return k.cast(x);
}
throw new NoSuchFieldError("the Unsafe");
}});
} catch (java.security.PrivilegedActionException e) {
throw new RuntimeException("Could not initialize intrinsics",
e.getCause());
}
}
}

0 comments on commit fe42313

Please sign in to comment.