Java Language
sun.misc.Unsafe
Sök…
Anmärkningar
Unsafe
klassen tillåter ett program att göra saker som inte är tillåtna av Java-kompilatorn. Normala program bör undvika att använda Unsafe
.
VARNINGAR
Om du gör ett misstag med att använda
Unsafe
API: er kan dina applikationer leda till att JVM kraschar och / eller uppvisar symtom som är svåra att diagnostisera.Det
Unsafe
API kan ändras utan föregående meddelande. Om du använder den i din kod kan du behöva skriva om koden när du ändrar Java-versioner.
Instantiating sun.misc.Ansafe via reflektion
public static Unsafe getUnsafe() {
try {
Field unsafe = Unsafe.class.getDeclaredField("theUnsafe");
unsafe.setAccessible(true);
return (Unsafe) unsafe.get(null);
} catch (IllegalAccessException e) {
// Handle
} catch (IllegalArgumentException e) {
// Handle
} catch (NoSuchFieldException e) {
// Handle
} catch (SecurityException e) {
// Handle
}
}
sun.misc.Unsafe
har en privat konstruktör och getUnsafe()
statisk getUnsafe()
med en kontroll av klasslastaren för att säkerställa att koden laddades med den primära klasslastaren. Därför är en metod för att ladda instansen att använda reflektion för att få det statiska fältet.
Instantiating sun.misc.Unsafe via bootclasspath
public class UnsafeLoader {
public static Unsafe loadUnsafe() {
return Unsafe.getUnsafe();
}
}
Även om detta exempel kommer att kompilera, kommer det troligtvis att misslyckas vid körning om inte klassen Unsafe laddades med den primära klasslastaren. För att säkerställa att det händer bör JVM laddas med lämpliga argument, som:
java -Xbootclasspath:$JAVA_HOME/jre/lib/rt.jar:./UnsafeLoader.jar foo.bar.MyApp
foo.bar.MyApp
klassen kan sedan använda UnsafeLoader.loadUnsafe()
.
Att få instansen av osäker
Osäker lagras som ett privat fält som inte kan nås direkt. Konstruktören är privat och den enda metoden för att komma åt public static Unsafe getUnsafe()
har privilegierad åtkomst. Genom att använda reflektion finns det ett arbete för att göra privata fält tillgängliga:
public static final Unsafe UNSAFE;
static {
Unsafe unsafe = null;
try {
final PrivilegedExceptionAction<Unsafe> action = () -> {
final Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return (Unsafe) f.get(null);
};
unsafe = AccessController.doPrivileged(action);
} catch (final Throwable t) {
throw new RuntimeException("Exception accessing Unsafe", t);
}
UNSAFE = unsafe;
}
Användning av osäker
Vissa användningar av osäkra är följande:
Använda sig av | API |
---|---|
Från heap / direkt minne allokering, omfördelning och omlokalisering | allocateMemory(bytes) , reallocateMemory(address, bytes) och freeMemory(address) |
Minnesstängsel | loadFence() , storeFence() , fullFence() |
Parkeringsströmtråd | park(isAbsolute, time) , unpark(thread) |
Direktfält och eller minnesåtkomst | get* och put* familj av metoder |
Kasta underkontrollerade undantag | throwException(e) |
CAS och Atomic Operations | compareAndSwap* |
Ställa in minnet | setMemory |
Flyktiga eller samtidiga operationer | get*Volatile , put*Volatile , putOrdered* |
Get and put-familjens metoder är relativt ett givet objekt. Om objektet är noll behandlas det som en absolut adress.
// Putting a value to a field
protected static long fieldOffset = UNSAFE.objectFieldOffset(getClass().getField("theField"));
UNSAFE.putLong(this, fieldOffset , newValue);
// Puting an absolute value
UNSAFE.putLong(null, address, newValue);
UNSAFE.putLong(address, newValue);
Vissa metoder definieras endast för int och länge. Du kan använda dessa metoder på floats och dubbel med floatToRawIntBits
, intBitsToFloat,
doubleToRawLongBits ,
longBitsToDouble`