Поиск…


замечания

Класс Unsafe позволяет программе выполнять действия, которые не допускаются компилятором Java. Обычным программам следует избегать использования Unsafe .

ПРЕДУПРЕЖДЕНИЯ

  1. Если вы ошиблись, используя Unsafe API, ваши приложения могут привести к сбою и / или выявлению симптомов, которые трудно диагностировать.

  2. Unsafe API может быть изменен без предварительного уведомления. Если вы используете его в своем коде, вам может потребоваться переписать код при изменении версий Java.

Выполнение sun.misc.Unsafe через отражение

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 имеет частный конструктор, а статический getUnsafe() проверкой загрузчика классов, чтобы обеспечить загрузку кода с помощью загрузчика основного класса. Поэтому одним из способов загрузки экземпляра является использование отражения для получения статического поля.

Выполнение sun.misc.Unsafe через bootclasspath

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

Хотя этот пример будет скомпилирован, он, скорее всего, потерпит неудачу во время выполнения, если класс Unsafe не будет загружен с помощью основного загрузчика классов. Чтобы убедиться, что JVM должен быть загружен с соответствующими аргументами, например:

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

Затем класс foo.bar.MyApp может использовать UnsafeLoader.loadUnsafe() .

Получение экземпляра небезопасного

Небезопасно хранится как частное поле, к которому невозможно получить доступ напрямую. Конструктор является закрытым и единственным способом доступа к public static Unsafe getUnsafe() имеет привилегированный доступ. Используя рефлексию, можно сделать доступными частные поля:

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

Использование небезопасных

Ниже перечислены некоторые виды использования небезопасных:

использование API
Отключение кучи / прямой памяти, перераспределение и освобождение памяти allocateMemory(bytes) , reallocateMemory(address, bytes) и freeMemory(address)
Запонки памяти loadFence() , storeFence() , fullFence()
Стоянка тока park(isAbsolute, time) , unpark(thread)
Прямой доступ к полю и памяти get* и put* семейство методов
Выброс исключенных исключений throwException(e)
CAS и атомные операции compareAndSwap* семейство методов
Настройка памяти setMemory
Неустойчивые или параллельные операции get*Volatile , put*Volatile , putOrdered*

Получаемое семейство методов относится к данному объекту. Если объект имеет значение null, он рассматривается как абсолютный адрес.

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

Некоторые методы определены только для int и longs. Вы можете использовать эти методы для поплавков и удвоений, используя floatToRawIntBits , intBitsToFloat, doubleToRawLongBits , longBitsToDouble`



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow