Ricerca…


Osservazioni

La classe Unsafe consente a un programma di eseguire operazioni che non sono consentite dal compilatore Java. I programmi normali dovrebbero evitare l'uso di Unsafe .

AVVERTENZE

  1. Se commetti un errore utilizzando le API non Unsafe , le tue applicazioni potrebbero causare l'arresto anomalo della JVM e / o mostrare sintomi difficili da diagnosticare.

  2. L'API Unsafe è soggetta a modifiche senza preavviso. Se lo si utilizza nel codice, potrebbe essere necessario riscrivere il codice quando si cambiano le versioni di Java.

Instantiating sun.misc.Unsafe tramite riflessione

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 ha un costruttore privato e il metodo statico getUnsafe() è protetto con un controllo del classloader per garantire che il codice sia stato caricato con il programma di caricamento di classe primario. Pertanto, un metodo per caricare l'istanza è utilizzare la riflessione per ottenere il campo statico.

Istanziazione di sun.misc.Unsafe tramite bootclasspath

public class UnsafeLoader {
    public static Unsafe loadUnsafe() {
        return Unsafe.getUnsafe();
    }
}

Mentre questo esempio verrà compilato, è probabile che fallisca in fase di esecuzione a meno che la classe Unsafe non sia stata caricata con il classloader primario. Per garantire che ciò accada, la JVM dovrebbe essere caricata con gli argomenti appropriati, come:

java -Xbootclasspath:$JAVA_HOME/jre/lib/rt.jar:./UnsafeLoader.jar foo.bar.MyApp

La classe foo.bar.MyApp può quindi utilizzare UnsafeLoader.loadUnsafe() .

Ottenere istanza di non sicuro

Unsafe è memorizzato come campo privato a cui non è possibile accedere direttamente. Il costruttore è privato e l'unico metodo per accedere al public static Unsafe getUnsafe() ha accesso privilegiato. Con l'uso della riflessione, c'è un work-around per rendere accessibili i campi privati:

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;
}

Usi di non sicuro

Alcuni usi non sicuri sono i seguenti:

Uso API
Off heap / allocazione diretta della memoria, riallocazione e deallocazione allocateMemory(bytes) , reallocateMemory(address, bytes) e freeMemory(address)
Recinti di memoria loadFence() , storeFence() , fullFence()
Filo di corrente di parcheggio park(isAbsolute, time) , unpark(thread)
Campo diretto e / o accesso alla memoria get* e put* famiglia di metodi
Lancio di eccezioni non controllate throwException(e)
CAS e operazioni atomiche compareAndSwap* famiglia di metodi
Impostazione della memoria setMemory
Operazioni volatili o concorrenti get*Volatile , put*Volatile , putOrdered*

La famiglia di metodi get e put è relativa a un determinato oggetto. Se l'oggetto è nullo, viene trattato come un indirizzo assoluto.

// 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);

Alcuni metodi sono definiti solo per int e long. Puoi usare questi metodi su float e doubles usando floatToRawIntBits , intBitsToFloat, doubleToRawLongBits , longBitsToDouble`



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow