java создания Почему существует sun.misc.Unsafe и как его можно использовать в реальном мире?



unsafe android (13)

На днях я наткнулся на sun.misc.Unsafe пакет и был поражен тем, что он мог сделать.

Конечно, класс недокументирован, но мне было интересно, если есть веская причина его использовать. Какие сценарии могут возникнуть там, где вам нужно будет их использовать? Как он может быть использован в реальном мире?

Кроме того, если вам это нужно, значит, это не указывает на то, что что-то не так с вашим дизайном?

Почему Java даже включает этот класс?


Answer #1

Основываясь на очень краткий анализ библиотеки Java 1.6.12 с использованием eclipse для отслеживания ссылок, кажется, что каждая полезная функциональность Unsafe раскрывается полезными способами.

Операции CAS отображаются через классы Atomic *. Функции манипуляций с памятью отображаются через команды DirectByteBuffer Sync (park, unpark), которые отображаются через AbstractQueuedSynchronizer, который, в свою очередь, используется реализациями Lock.


Answer #2

Unsafe.throwException - позволяет исключить проверенное исключение, не объявляя их.

Это полезно в некоторых случаях, когда вы имеете дело с отражением или АОП.

Предположим, что вы создаете общий прокси для пользовательского интерфейса. И пользователь может указать, какое исключение вызывается импликацией в специальном случае, просто объявив исключение в интерфейсе. Тогда это единственный способ, которым я знаю, создать проверенное исключение в динамической реализации интерфейса.

import org.junit.Test;
/** need to allow forbidden references! */ import sun.misc.Unsafe;

/**
 * Demonstrate how to throw an undeclared checked exception.
 * This is a hack, because it uses the forbidden Class {@link sun.misc.Unsafe}.
 */
public class ExceptionTest {

    /**
     * A checked exception.
     */
    public static class MyException extends Exception {
        private static final long serialVersionUID = 5960664994726581924L;
    }

    /**
     * Throw the Exception.
     */
    @SuppressWarnings("restriction")
    public static void throwUndeclared() {
        getUnsafe().throwException(new MyException());
    }

    /**
     * Return an instance of {@link sun.misc.Unsafe}.
     * @return THE instance
     */
    @SuppressWarnings("restriction")
    private static Unsafe getUnsafe() {
        try {

            Field singleoneInstanceField = Unsafe.class.getDeclaredField("theUnsafe");
            singleoneInstanceField.setAccessible(true);
            return (Unsafe) singleoneInstanceField.get(null);

        } catch (IllegalArgumentException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (SecurityException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (NoSuchFieldException e) {
            throw createExceptionForObtainingUnsafe(e);
        } catch (IllegalAccessException e) {
            throw createExceptionForObtainingUnsafe(e);
        }
    }

    private static RuntimeException createExceptionForObtainingUnsafe(final Throwable cause) {
        return new RuntimeException("error while obtaining sun.misc.Unsafe", cause);
    }


    /**
     * scenario: test that an CheckedException {@link MyException} can be thrown
     * from an method that not declare it.
     */
    @Test(expected = MyException.class)
    public void testUnsingUnsaveToThrowCheckedException() {
        throwUndeclared();
    }
}

Answer #3

Класс Unsafe

Набор методов для выполнения низкоуровневых, небезопасных операций. Хотя класс и все методы являются общедоступными, использование этого класса ограничено, потому что только доверенный код может получить его экземпляры.

Одно из них - в java.util.concurrent.atomic классах:


Answer #4

Не использовал его сам, но я полагаю, что если у вас есть переменная, которую иногда читают более чем один поток (так что вы действительно не хотите, чтобы она была изменчивой), вы могли бы использовать putObjectVolatile при записи в основной поток и readObjectVolatile при выполнении редких чтений из других потоков.


Answer #5

Объект, по-видимому, доступен для работы на более низком уровне, чем обычно позволяет код Java. Если вы кодируете приложение высокого уровня, JVM абстрагирует обработку памяти и другие операции от уровня кода, поэтому ее проще программировать. Используя библиотеку Unsafe, вы эффективно выполняете операции низкого уровня, которые обычно выполняются для вас.

Поскольку woliveirajr заявил, что «random ()» использует Unsafe для семян, так же, как и многие другие операции будут использовать функцию allocateMemory (), включенную в Unsafe.

Как программист, вы, вероятно, могли бы уйти, никогда не нуждаясь в этой библиотеке, но жесткий контроль над элементами низкого уровня пригодится (поэтому по-прежнему существует сборка и (в меньшей степени) код C, дрейфующий в основных продуктах)


Answer #6

Коллекции вне кучи могут быть полезны для выделения огромных объемов памяти и освобождения их сразу после использования без помех GC. Я написал library для работы с массивами / списками вне массивов на основе sun.misc.Unsafe .


Answer #7

Недавно я работал над переориентацией JVM и обнаружил, что удивительное количество классов реализовано с точки зрения Unsafe . Класс в основном предназначен для разработчиков библиотеки Java и содержит функции, которые являются принципиально небезопасными, но необходимыми для создания быстрых примитивов. Например, существуют методы получения и записи исходных смещений полей, использование аппаратной синхронизации, выделение и освобождение памяти и т. Д. Он не предназначен для использования нормальными Java-программистами; он недокументирован, специфичен для реализации и по своей сути небезопасен (отсюда и название!). Более того, я считаю, что SecurityManager будет запрещать доступ к нему почти во всех случаях.

Короче говоря, он в основном существует, чтобы позволить библиотечным реализаторам доступ к базовому компьютеру без необходимости объявлять каждый метод в определенных классах, например AtomicInteger . Вы не должны использовать или беспокоиться об этом в рутинном программировании на Java, так как все дело в том, чтобы сделать остальные библиотеки достаточно быстрыми, чтобы вам не нужен такой доступ.


Answer #8

Для эффективной копии памяти (быстрее скопировать, чем System.arraycopy () для коротких блоков, по крайней мере); как используется LZF Java LZF и Snappy . Они используют «getLong» и «putLong», которые быстрее, чем копирование побайтно; особенно эффективны при копировании таких вещей, как блоки 16/32/64 байтов.



Answer #10

Интересно, я даже не слышал об этом классе (что, вероятно, хорошо, действительно).

Одна вещь, которая Unsafe#setMemory в голову, заключается в использовании Unsafe#setMemory для обнуления буферов, содержащих конфиденциальную информацию в одной точке (пароли, ключи, ...). Вы могли бы даже сделать это в полях «неизменяемых» объектов (тогда, опять же, я полагаю, что простое старое отражение может сделать здесь трюк). Я не эксперт по вопросам безопасности, хотя и принимаю это с солью.


Answer #11

Просто от запуска search в некоторой поисковой системе кода я получаю следующие примеры:

Простой класс для доступа к объекту {@link Unsafe}. {@link Unsafe} * требуется для эффективной работы CAS на массивах. Обратите внимание, что версии в {@link java.util.concurrent.atomic}, такие как {@link java.util.concurrent.atomic.AtomicLongArray}, требуют дополнительных гарантий упорядочения памяти, которые обычно не нужны в этих алгоритмах и также дороги на большинстве процессоров.

  • SoyLatte - java 6 для вывода osx javadoc

/ ** Базовый класс для sun.misc.Unsafe FieldAccessors для статических полей. Наблюдение состоит в том, что с точки зрения кода отражения есть только девять типов полей: восемь примитивных типов и Object. Использование класса Unsafe вместо генерируемых байт-кодов экономит память и время загрузки для динамически генерируемых FieldAccessors. * /

  • SpikeSource

/ * FinalFields, которые отправляются через провод. Как размонтировать и воссоздать объект на принимающей стороне? Мы не хотим вызывать конструктор, так как он будет устанавливать значения для конечных полей. Мы должны воссоздать окончательное поле точно так же, как и на стороне отправителя. Sun.misc.Unsafe делает это для нас. * /

Есть много других примеров, просто следуйте приведенной выше ссылке ...


Answer #12

Это вам нужно, если вам нужно заменить функциональность, предоставляемую одним из классов, который использует ее в настоящее время.

Это может быть обычная / более быстрая / более компактная сериализация / десериализация, более быстрая / большая версия ByteBuffer с буфером / изменением размера или добавление атомной переменной, например, не поддерживаемой в настоящее время.

Я использовал его для всех из них в какое-то время.


Answer #13

Мы внедрили огромные коллекции, такие как массивы, HashMaps, TreeMaps, используя Unsafe.
И чтобы избежать / минимизировать фрагментацию, мы реализовали распределитель памяти, используя концепции dlmalloc over unsafe.
Это помогло нам добиться производительности в параллелизме.





unsafe