Szukaj…


Uwagi

Klasa Unsafe umożliwia programowi wykonywanie czynności, które nie są dozwolone przez kompilator Java. Normalne programy powinny unikać korzystania z Unsafe .

OSTRZEŻENIA

  1. Jeśli popełnisz błąd przy użyciu Unsafe interfejsów API, Twoje aplikacje mogą spowodować awarię JVM i / lub objawy trudne do zdiagnozowania.

  2. Unsafe interfejs API może ulec zmianie bez powiadomienia. Jeśli użyjesz go w kodzie, może być konieczne przepisanie kodu podczas zmiany wersji Java.

Tworzenie instancji sun.misc.Unsafe przez odbicie

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 ma konstruktora prywatnego, a statyczna getUnsafe() jest chroniona przez sprawdzenie modułu ładującego klasy, aby upewnić się, że kod został załadowany za pomocą głównego modułu ładującego klasy. Dlatego jedną z metod ładowania instancji jest użycie odbicia w celu uzyskania pola statycznego.

Tworzenie instancji sun.misc.Unsafe przez bootclasspath

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

Chociaż ten przykład się skompiluje, prawdopodobnie zakończy się niepowodzeniem w czasie wykonywania, chyba że klasa niebezpieczna została załadowana za pomocą podstawowego modułu ładującego klasy. Aby mieć pewność, że tak się stanie, do maszyny JVM należy załadować odpowiednie argumenty, takie jak:

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

Klasa foo.bar.MyApp może następnie użyć UnsafeLoader.loadUnsafe() .

Uzyskiwanie wystąpienia niebezpiecznego

Niebezpieczne są przechowywane jako prywatne pola, do których nie można uzyskać bezpośredniego dostępu. Konstruktor jest prywatny i jedyną metodą dostępu do public static Unsafe getUnsafe() ma uprzywilejowany dostęp. Dzięki zastosowaniu refleksji można obejść problem, aby udostępnić pola prywatne:

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

Zastosowania niebezpieczne

Niektóre zastosowania niebezpieczne są następujące:

Posługiwać się API
Przydział pamięci / bezpośrednie przydzielanie, realokacja i dezalokacja allocateMemory(bytes) , reallocateMemory(address, bytes) i freeMemory(address)
Ogrodzenia pamięci loadFence() , storeFence() , fullFence()
Prąd bieżący parkowania park(isAbsolute, time) , unpark(thread)
Bezpośredni dostęp do pola i / lub pamięci get* i put* rodzinę metod
Zgłaszanie niezaznaczonych wyjątków throwException(e)
CAS i operacje atomowe rodzina metod compareAndSwap*
Określanie pamięci setMemory
Lotne lub równoległe operacje get*Volatile , put*Volatile , putOrdered*

Rodzina metod get i put odnosi się do danego obiektu. Jeśli obiekt ma wartość NULL, to jest traktowany jako adres bezwzględny.

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

Niektóre metody są zdefiniowane tylko dla int i longs. Tych metod można używać na floatToRawIntBits intBitsToFloat, i podwójnych za pomocą floatToRawIntBits , intBitsToFloat, doubleToRawLongBits , longBitsToDouble`



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow