Java Language
sun.misc.Unsafe
Zoeken…
Opmerkingen
Met de klasse Unsafe
kan een programma dingen doen die niet zijn toegestaan door de Java-compiler. Normale programma's moeten het gebruik van Unsafe
vermijden.
WAARSCHUWINGEN
Als u een fout maakt met de
Unsafe
API's, kunnen uw toepassingen de JVM laten crashen en / of symptomen vertonen die moeilijk te diagnosticeren zijn.De
Unsafe
API kan zonder kennisgeving worden gewijzigd. Als u het in uw code gebruikt, moet u de code mogelijk herschrijven wanneer u Java-versies wijzigt.
Sunmisc instantiëren. Onveilig via reflectie
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
heeft een sun.misc.Unsafe
en de statische methode getUnsafe()
wordt bewaakt met een vinkje bij de classloader om te controleren of de code is geladen met de primaire classloader. Daarom is een methode voor het laden van de instantie om reflectie te gebruiken om het statische veld te krijgen.
Sunmisc instantiëren. Onveilig via bootclasspath
public class UnsafeLoader {
public static Unsafe loadUnsafe() {
return Unsafe.getUnsafe();
}
}
Hoewel dit voorbeeld wordt gecompileerd, mislukt het waarschijnlijk tijdens runtime, tenzij de klasse Onveilig is geladen met de primaire classloader. Om ervoor te zorgen dat dit gebeurt, moet de JVM worden geladen met de juiste argumenten, zoals:
java -Xbootclasspath:$JAVA_HOME/jre/lib/rt.jar:./UnsafeLoader.jar foo.bar.MyApp
De klasse foo.bar.MyApp
kan vervolgens UnsafeLoader.loadUnsafe()
.
Instance van onveilig
Onveilig wordt opgeslagen als een privéveld dat niet rechtstreeks toegankelijk is. De constructor is privé en de enige methode voor toegang tot public static Unsafe getUnsafe()
heeft bevoorrechte toegang. Door middel van reflectie is er een omweg om privévelden toegankelijk te maken:
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;
}
Gebruik van onveilig
Sommige toepassingen van onveilig is als volgt:
Gebruik | API |
---|---|
Off heap / directe geheugentoewijzing, hertoewijzing en deallocatie | allocateMemory(bytes) , reallocateMemory(address, bytes) en freeMemory(address) |
Geheugen hekken | loadFence() , storeFence() , fullFence() |
Huidige draad parkeren | park(isAbsolute, time) , unpark(thread) |
Direct veld en of geheugentoegang | get* en put* familie van methoden |
Ongecontroleerde uitzonderingen gooien | throwException(e) |
CAS en Atomic Operations | compareAndSwap* familie van methoden |
Geheugen instellen | setMemory |
Vluchtige of gelijktijdige operaties | get*Volatile , put*Volatile , putOrdered* |
De get en put-familie van methoden is relatief ten opzichte van een bepaald object. Als het object nul is, wordt het behandeld als een absoluut adres.
// 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);
Sommige methoden zijn alleen gedefinieerd voor int en longs. U kunt deze methoden gebruiken voor drijvers en dubbels met floatToRawIntBits
, intBitsToFloat,
doubleToRawLongBits ,
longBitsToDouble`