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

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

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



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow