Recherche…


Remarques

La classe Unsafe permet à un programme de faire des choses qui ne sont pas autorisées par le compilateur Java. Les programmes normaux devraient éviter d'utiliser Unsafe .

AVERTISSEMENTS

  1. Si vous commettez une erreur en utilisant les API Unsafe , vos applications risquent de provoquer le blocage de la JVM et / ou de présenter des symptômes difficiles à diagnostiquer.

  2. L'API Unsafe est sujet à modification sans préavis. Si vous l'utilisez dans votre code, vous devrez peut-être réécrire le code lors de la modification des versions de Java.

Instanciation de sun.misc.Unsafe via la réflexion

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 possède un constructeur Private et la getUnsafe() statique getUnsafe() est protégée par une vérification du chargeur de classe pour garantir que le code a été chargé avec le chargeur de classe principal. Par conséquent, une méthode de chargement de l'instance consiste à utiliser la réflexion pour obtenir le champ statique.

Instanciation de sun.misc.Unsafe via bootclasspath

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

Bien que cet exemple compile, il est probable qu'il échoue à l'exécution à moins que la classe Unsafe ne soit chargée avec le chargeur de classe principal. Pour que cela se produise, la JVM doit être chargée avec les arguments appropriés, tels que:

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

La classe foo.bar.MyApp peut alors utiliser UnsafeLoader.loadUnsafe() .

Obtenir l'instance de Unsafe

Unsafe est stocké dans un champ privé auquel on ne peut pas accéder directement. Le constructeur est privé et la seule méthode pour accéder à public static Unsafe getUnsafe() a un accès privilégié. En utilisant la réflexion, il existe un moyen de contourner les domaines privés:

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

Utilisations de Unsafe

Voici quelques utilisations de unsafe:

Utilisation API
Allocation de mémoire / mémoire directe, réaffectation et désallocation allocateMemory(bytes) , reallocateMemory(address, bytes) et freeMemory(address)
Clôtures à mémoire loadFence() , storeFence() , fullFence()
Fil de stationnement actuel park(isAbsolute, time) , unpark(thread)
Accès direct au champ et / ou à la mémoire get* et put* famille de méthodes
Lancer des exceptions non vérifiées throwException(e)
CAS et opérations atomiques Famille de méthodes compareAndSwap*
Mise en mémoire setMemory
Opérations volatiles ou simultanées get*Volatile , put*Volatile , putOrdered*

La famille de méthodes get et put est relative à un objet donné. Si l'objet est nul, il est traité comme une adresse absolue.

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

Certaines méthodes ne sont définies que pour int et longs. Vous pouvez utiliser ces méthodes sur floats et doubles en utilisant floatToRawIntBits , intBitsToFloat, doubleToRawLongBits , longBitsToDouble`



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow