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

  1. 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.

  2. 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`



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow