Статьи

Чему нас учит sun.misc. Небезопасное страдание

Oracle удалит внутренний класс sun.misc.Unsafe в Java 9 . Хотя большинство людей, вероятно, довольно безразлично относятся к этому изменению, некоторые другие — в основном разработчики библиотек — нет. В блогосфере было несколько недавних статей, рисующих мрачную картину того, что будет означать это изменение:

Поддержание общедоступного API чрезвычайно сложно, особенно когда API так же популярен, как и JDK. Просто (почти) невозможно удержать людей от стрельбы в ноги. Oracle (и ранее Sun) всегда объявляли пакеты sun.* Как внутренние и не используемые. Ссылаясь на страницу «Почему разработчики не должны писать программы, которые называют« солнечными »пакетами» :

Пакеты sun. * Не являются частью поддерживаемого общедоступного интерфейса.

Программа Java, которая напрямую обращается к пакетам sun. *, Не гарантирует работу на всех Java-совместимых платформах. На самом деле, такая программа не гарантирует работу даже в будущих версиях на той же платформе.

Этот отказ от ответственности является лишь одним из многих подобных заявлений об отказе от ответственности и предупреждений. Тот, кто идет вперед и использует Unsafe делает это … « небезопасно ».

Что мы узнаем из этого?

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

Но есть более важное сообщение ко всему этому. Сообщение:

Когда все, что у вас есть, это молоток, каждая проблема выглядит как большой палец

Переведено в эту ситуацию: молоток Unsafe и, учитывая, что это очень плохой молоток, но единственный вариант, ну, у разработчиков библиотеки, возможно, просто не было большого выбора. Они на самом деле не виноваты. Фактически, они рискнули сыграть в одной из самых стабильных и обратно совместимых программных сред (= Java), и они преуспели в этом более 10 лет. Вы бы сделали другой выбор в подобной ситуации? Или позвольте мне спросить по-другому. В то время ставки на AWT или Swing были намного безопаснее?

Если что-то кто-то может каким-то образом использовать, то это будет, независимо от того, насколько очевидно, что они будут стрелять себе в ноги. Единственный способ в настоящее время написать библиотеку / API и по-настоящему запретить пользователям доступ к внутренним объектам — это собрать все в один пакет и сделать его закрытым. Это то, что мы делали в jOOQ с самого начала, зная, что внутренности jOOQ чрезвычайно деликатны и постоянно меняются.

Более подробную информацию об этом обосновании читайте также:

Однако это решение имеет серьезный недостаток для тех, кто разрабатывает эти внутренние компоненты. Это адский пакет почти без структуры. Это делает разработку довольно сложной.

Что было бы лучше Java, тогда?

У Java всегда был недостаточный набор видений :

  • public
  • protected
  • default (package-private)
  • private

Должна быть пятая видимость, которая ведет себя как public но запрещает доступ «снаружи» модуля. В некотором смысле, это между существующей public и default видимостью. Давайте назовем это гипотетическим module видимости.

На самом деле, мы не только должны быть в состоянии объявить эту видимость для класса или члена, мы должны быть в состоянии управлять взаимозависимостями модулей на верхнем уровне, как это делает язык Цейлона :

1
2
3
4
5
module org.hibernate "3.0.0.beta" {
    import ceylon.collection "1.0.0";
    import java.base "7";
    shared import java.jdbc "7";
}

Это очень похоже на систему комплектов OSGi, где комплекты можно импортировать / экспортировать, хотя приведенный выше синтаксис модуля намного проще, чем настройка OSGi.

Сложная модульная система пошла бы еще дальше. Он не только будет соответствовать функциям OSGi, но и Maven. С возможностью объявления зависимостей на основе модуля языка Java нам больше не понадобятся дескрипторы Maven на основе XML, так как они могут быть сгенерированы из простого синтаксиса модуля (или Gradle, или ant / ivy).

И с sun.misc.Unsafe всего этого классы вроде sun.misc.Unsafe могут быть объявлены как видимые модулями только для нескольких модулей JDK — не для всего мира. Я уверен, что число людей, злоупотребляющих рефлексией, чтобы овладеть этими внутренностями, уменьшится на 50%.

Вывод

Я очень надеюсь, что в будущем Java эта функция языка Цейлона ( а также функция языка Fantom, кстати ) будет включена в язык Java. Хороший обзор модульной инкапсуляции Java 9 / Jigsaw можно увидеть в этом блоге: http://blog.codefx.org/java/dev/features-project-jigsaw-java-9/#Encapsulation

До этого, если вы дизайнер API, знайте, что все отказы от ответственности не будут работать. Ваши внутренние API будут использоваться и злоупотребляться вашими клиентами. Они являются частью вашего обычного публичного API с первого дня после их публикации. Это не вина вашего пользователя. Вот как все работает.

Ссылка: Чему нас учит sun.misc.Unsafe: от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и JOOQ .