Java Language
sun.misc.Unsafe
Suche…
Bemerkungen
Mit der Unsafe
Klasse kann ein Programm Dinge Unsafe
, die der Java-Compiler nicht zulässt. Bei normalen Programmen sollte Unsafe
.
WARNUNGEN
Wenn Sie bei der Verwendung der
Unsafe
API einen Fehler machen,Unsafe
Ihre Anwendungen dazu, dass die JVM abstürzt und / oder Symptome aufweist, die schwer zu diagnostizieren sind.Die
Unsafe
API kann ohne vorherige Ankündigung geändert werden. Wenn Sie es in Ihrem Code verwenden, müssen Sie den Code möglicherweise ändern, wenn Sie die Java-Version ändern.
Instanziieren von sun.misc.Unsafe durch 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
verfügt über einen privaten Konstruktor, und die statische Methode getUnsafe()
wird durch eine Überprüfung des Klassenladers überwacht, um sicherzustellen, dass der Code mit dem primären Klassenlader geladen wurde. Daher besteht eine Methode zum Laden der Instanz darin, das statische Feld mithilfe von Reflektion zu erhalten.
Sun.misc.Unsafe über den Bootclasspath instanziieren
public class UnsafeLoader {
public static Unsafe loadUnsafe() {
return Unsafe.getUnsafe();
}
}
Während dieses Beispiel kompiliert wird, schlägt es wahrscheinlich zur Laufzeit fehl, wenn die Unsafe-Klasse nicht mit dem primären Classloader geladen wurde. Um sicherzustellen, dass dies geschieht, sollte die JVM mit den entsprechenden Argumenten geladen werden, z.
java -Xbootclasspath:$JAVA_HOME/jre/lib/rt.jar:./UnsafeLoader.jar foo.bar.MyApp
Die Klasse foo.bar.MyApp
kann dann UnsafeLoader.loadUnsafe()
.
Instanz von unsicher erhalten
Unsafe wird als privates Feld gespeichert, auf das nicht direkt zugegriffen werden kann. Der Konstruktor ist privat und die einzige Methode für den Zugriff auf public static Unsafe getUnsafe()
hat privilegierten Zugriff. Mithilfe von Reflektionen wird eine Problemumgehung durchgeführt, um private Felder zugänglich zu machen:
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;
}
Verwendung von unsicher
Einige Verwendungen von unsicher ist s:
Benutzen | API |
---|---|
Off-Heap / Direct-Speicherzuweisung, Neuzuweisung und Freigabe | allocateMemory(bytes) , reallocateMemory(address, bytes) und freeMemory(address) |
Gedächtniszäune | loadFence() , storeFence() , fullFence() |
Parkstrom-Thread | park(isAbsolute, time) , unpark(thread) |
Direkter Feld- und / oder Speicherzugriff | get* und put* Methodenfamilie |
Ungeprüfte Ausnahmen werfen | throwException(e) |
CAS und Atomic Operations | compareAndSwap* Methodenfamilie |
Speicher einrichten | setMemory |
Flüchtige oder gleichzeitige Operationen | putOrdered* get*Volatile , put*Volatile , putOrdered* |
Die Methoden von get und put sind relativ zu einem gegebenen Objekt. Wenn das Objekt null ist, wird es als absolute Adresse behandelt.
// 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);
Einige Methoden sind nur für int und longs definiert. Sie können diese Methoden für Floats und Doubles verwenden, indem Sie floatToRawIntBits
, intBitsToFloat,
doubleToRawLongBits ,
longBitsToDouble` verwenden