Java 9 наконец-то разберется с зависимостями


Оглавление (нажмите, чтобы открыть):

5 нововведений в Java 9

Перед вами вольный перевод статьи на тему интересных нововведений в Java 9.

Какие наиболее интересные вещи ожидаются с релизом Java 9?

Несмотря на относительную тишину про Java 9, разработчики JDK усердно работают, подготавливая следующий релиз, который ожидается всего через несколько месяцев — в декабре 2015 года. После этого, будет проведено тщательное тестирование и подготовка к публичному релизу, запланированному на сентябрь 2020 года.

Сейчас уже есть довольно чёткое представление того, что стоит ожидать в Java 9.

Если Java 8 может быть описана как версия с упором на лямбды, стримы и изменения API, то Java 9 полностью посвящена Jigsaw (основная цель — разбить JRE и принести модульность в компоненты ядра Java), дополнительным утилитам и изменениям ядра. В этой статье собраны некоторые нововведения Java 9, которые мы считаем наиболее интересными.

Перечисленные ниже нововведения уже готовы и могут быть опробованы вами в ранней версии Java 9.

1. Java + REPL = jshell

Ранее были сомнения, что Kulla успеет к Java 9. Но сейчас стало известно, что в следующем релизе Java одной из новых особенностей будет новая утилита для работы с командной строкой. Она называется jshell. Она добавит встроенную поддержку REPL (Read-Eval-Print-Loop) в Java. Т.е. если вы захотите запустить несколько строк кода на Java, то вам не придётся оборачивать их в классы или выделять отдельный проект. Так же можно забыть про точки с запятой:

Существует несколько альтернативных решений получения REPL — в виде аддонов для популярных IDE или web консоли, но официального решения не существовало до сих пор. jshell уже доступен в ранней версии Java 9.

2. Микробенчмарки на подходе

Java Microbenchmarking Harness (JMH) Алексея Шипилева (Alexey Shipilev) делает новый шаг в своём развитии и присоединяется к Java, как официальный бенчмарк.

Если вы хотите получить наиболее точные результаты, которые помогут принять вам правильное решение, то, на сегодняшний день, JMH — лучший выбор. И теперь JMH становится частью Java 9.

3. Будет ли G1 новым сборщиком мусора по умолчанию?

Распространённым заблуждением считается, что в Java есть всего один сборщик мусора. На самом деле их целых 4.

На данный момент обсуждается установка G1 сборщиком мусора по умолчанию. G1 был впервые представлен в Java 7. Вообще G1 был спроектирован для улучшенной работы с “кучей” размером больше чем 4ГБ. G1 показывает более редкое срабатывание сборщика мусора, но время самого сбора, возрастает.

4. Будущее с HTTP 2.0

Несколько месяцев назад была утверждена спецификация HTTP 2.0 RFC, построенная поверх SPDY алгоритма от гугла. SPDY уже показала увеличение скорости относительно HTTP 1.1 в переделах 11.81%-47.7%. Большинство современных браузеров уже поддерживают данную технологию.

Java 9 будет полностью поддерживать протокол HTTP 2.0, а так же получит новый HTTP клиент, который придёт на замену старого HttpURLConnection. В новом HTTP клиенте будет реализована поддержка веб сокетов и HTTP 2.0.

5. Нововведения в process API

До сих пор возможность контроля и управления процессами операционной системы средствами Java были реализованы очень слабо. Например, раньше чтобы получить информацию о вашем PID нужно было использовать нативный код или прибегать к чёрной магии . Кроме того, данный подход требовал индивидуального решения для каждой из платформ.

До Java 9 код получения PID имел примерно следующий вид:

Теперь данный код может выглядеть следующим образом:

Обновление расширит возможности взаимодействия Java с операционной системой: новые методы для поиска идентификаторов процессов (PIDs), имена и состояния процессов и многое другое.

Чего мы не увидим в Java 9?

Две возможности, которые все хотели и ожидали увидеть, но которые так и не попадут в релиз Java 9.

Стандартизированные JSON API

За добавление JSON API голосовали так же усердно как за Jigsaw, но данный API так и не будет добавлен.


Главный архитектор платформы Java Марк Ренгольд (Mark Reinhold) в рассылке JDK 9 написал:

Эта система была бы полезным дополнение к платформе, но по большому счёту, это не так важно как остальные нововведения для JDK 9, финансируемые или рассматриваемые к финансированию ораклом. Мы можем пересмотреть это нововведение в JDK 10 или более поздних релизах.

API для работы с деньгами и валютами

Так же не будет добавлена поддержка работы с деньгами и валютой.

Как модули Java 9 решают проблемы, связанные с транзитивными зависимостями?

Я читал, что модули java 9 помогают решить проблемы, возникающие при извлечении нескольких версий одной и той же зависимости из-за переходных зависимостей. Я не понимаю почему. Если вы принесете несколько модулей, вы можете получить ту же проблему. Я имею в виду, если один из модулей содержит одну версию Hamcrest, а другие — другие тестовые инструменты, представляющие версии 2, 3, 4 или любую другую из mockito или junit. Как модули помогают с этой проблемой?

1 ответ

При поиске пути к модулю для модуля с конкретным именем система модулей берет первое определение модуля с таким именем. Строки версии, если они есть, игнорируются; если элемент пути к модулю содержит определения нескольких модулей с одинаковыми именами, то при разрешении происходит сбой, и компилятор, компоновщик или виртуальная машина сообщит об ошибке и завершит работу. В обязанности инструментов сборки и контейнерных приложений входит настройка путей модулей, чтобы избежать конфликтов версий; Целью модульной системы не является решение проблемы выбора версии.

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

Студия готового дизайна GS studio

Login

В конце мая я выступал на JEEConf 2020, где рассказывал об эффективности и производительности Java библиотек и фреймворков. Любое упоминание о производительности должно ссылаться на результаты измерений, что я и сделал во время доклада. Но я решил пойти дальше и протестировать один и тот же код на двух версиях — Java 8 и Java 9.

Хоть Java 9 и выходит только в июле (уже в сентябре), но она уже перешла в стадию Release Candidate, то есть никаких новых фич больше не будет и все критические баги должны быть исправлены. Я начал пользоваться Java 8 за 5 месяцев до релиза и никаких особых проблем при этом не испытал. В то же время главная фича новой версии — модуляризация (проект Jigsaw) привела к многочисленным изменениям внутри самой JDK. Хорошо было бы протестировать библиотеки на новой версии. В сети есть много статей и видео-докладов на тему проектирования модулей. Но сначала нужно проверить, а будет ли работать существующее приложение, и если будет, то как отразится миграция на скорости работы нашей системы. Не секрет, что многие компании остаются на старых версиях (Java 5 — 7) частично из-за боязни новых ошибок и проблем в производительности. Если же приложение работать не будет, насколько просто это починить?

Поэтому я призываю всех установить JDK 9 и протестировать свое приложение. Разумеется, вы можете и дальше использовать текущую версию Java, но прогресс не стоит на месте. Через пару лет выйдет Java 10, а с ней возможно и свойства, и value types, и все равно придется использовать модульность. Тем более что современные IDE (IntelliJ IDEA) уже поддерживают все фичи Java 9.

Системы сборки. Maven

Сборка проекта — это процесс, который проходит постоянно в течение рабочего дня как на компьютере разработчика, так и на CI сервере. Поэтому здесь требуется максимальное быстродействие. Для тестирования сборки я выбрал проект, который я разрабатываю в рамках книги «Разработка Java приложений», тем более что он поддерживает и Maven, и Gradle. Проект постоянно обновляется, поэтому версии зависимостей в нем года либо конца года. Вы сами можете скачать проект и протестировать на своей машине.

Поддерживают ли Maven/Gradle Java 9? Это интересный вопрос, тем более что их модель зависимостей чем-то похожа и даже является конкурентом JDK 9.

Итак, я установил JDK Early Access preview build 171 на Windows систему. Результат запуска команды «java -version»:

Начнем с Maven. Для тестирования я выбрал последнюю версию — 3.5.0. Сам Maven запускается без проблем, выдает корректную версию JDK:

Теперь запустим сборку проекта: mvn clean install. Сборка падает на этапе запуска тестов с ошибкой:

Почему-то стандартный класс JAXBException больше не находится. Дело в том, что все, связанное с JAXB, перенесено Java в модуль java.xml.bind, который автоматически не добавляется в modulepath при запуске JVM, потому что не входит в дефолтный модуль java . se. Как выйти из этого положения? Либо явно указать этот модуль для запуска JVM, либо агрегатный модуль java . se . ee, куда входит все, что связано с Java EE API. Разумеется, добавить агрегатный модуль удобнее, чем каждый модуль по отдельности. Поэтому добавляем переменную окружения MAVEN_OPTS (если у вас ее еще нет), и присваиваем ей значение «—add-modules java . se . ee».

Однако ошибка не исчезает. Все дело в том, что тесты запускает Maven Surfire плагин, который стартует новый JVM процесс. Для того, чтобы указать новые модули, нужно добавить Surfire плагин в главный pom.xml и передать параметры там:

Перезапускаем сборку и получаем новое исключение:

Эта проблема не имеет очевидного решения, потому что JTA библиотека (где находится класс SystemException) присутствует в class-path. Поэтому придется все же в Surfire плагине использовать модуль java.xml.bind:

Перезапускаем сборку Maven и получаем новое исключение:

В чем заключается ошибка? Hibernate пытается через reflection сделать публичным метод, который является protected или private. До Java 9 это было небезопасно, но возможно. Сейчас это запрещено, если только модуль, в котором находится метод, не объявлен открытым (open). Однако есть лазейка, помогает обойти это ограничение. Нужно добавить к аргументам JVM строку —add-opens java . base/java . lang=ALL-UNNAMED

Здесь мы указываем название модуля, затем пакет и тот модуль, для которого мы открываем доступ. Так как наш проект не использует модули, то мы указываем константу ALL-UNNAMED, которой открыт доступ для всех анонимных модулей. Анонимные модули — это обычные jar файлы, в которых нет файла конфигурации module-info . class. Они были добавлены, чтобы разработчикам библиотек было легче перейти на Java 9.


Добавляем эту строку к аргументам командной строки для плагина Surfire и перезапускаем сборку Maven. Получаем новое исключение, но уже при запуске других тестов:

Как вы видите из stacktrace, проблема происходит на стадии инициализации JMockit. Что можно сделать? Можно обновить версию Jmockit с 1.30 на 1.32. Но это не помогает. Уже готовится версия JMockit, но она все еще в стадии beta. Анализ исходников JDK позволяет обнаружить системную переменную JVM, которая позволяет присоединиться к текущей JVM из нее самое. Нужно лишь установить этот флаг в true: -Djdk.attach.allowAttachSelf=true. Подробнее можно прочесть здесь

Добавляем флаг к параметрам в Surefire плагине и перезапускаем сборку Maven. Получаем новую ошибку:

Подробнее об этой проблеме можно прочесть здесь.

А лечится она обновлением версии war-плагина с 2.6 на 3.1.0:

Меняем версию и перезапускаем сборку. Получаем новую ошибку:

С похожей проблемой мы уже сталкивались. Нужно лишь «открыть» доступ к пакетам, добавив параметры в MAVEN_OPTS:

Перезапускаем сборку Maven и получаем новую ошибку:

Stacktrace говорит об ошибке более подробно:

Проблема в том, что такого класса больше нет в JDK. Можно вручную добавить необходимые классы, как сделали здесь.

А можно обновить версию Lombok (c 1.16.14 до 1.16.16):

Перезапускаем сборку Maven и получаем новое исключение при запуске тестов:

После небольшого исследования выяснилось, что проблема исходит от библиотеки тестирования JGlue, однако его последняя версия была выпущена в июле 2020 года и неизвестно, насколько быстро выйдет новая версия.

На этом мое тестирование Maven завершилось. Часть проблем удалось решить, но в целом, их довольно много как для одного проекта. Проект собирается успешно, но часть тестов при этом не проходит.

Системы сборки. Gradle

Теперь проверим, насколько совместим Gradle с JDK 9. Возьмем последнюю версию первого — 3.5.0, обновим Lombok зависимость и запустим сборку: gradle clean install.

Получим довольно малоинформативную ошибку: java.lang.ExceptionInInitializerError (no error message). Поэтому добавим флаг —stacktrace, который даст больше информации:

Для того, чтобы избавиться от этой ошибки, добавляем знакомый аргумент add-opens в системную переменную GRADLE_OPTS:

Подробнее можно прочитать здесь и здесь.

Перезапускаем сборку Gradle, получаем новую ошибку:

Мастер Йода рекомендует:  Как разместить изображение на веб-странице слева от текста

В результат длительного исследования оказывается, что ситуация не так проста, как для Maven. Дело в том, что во время сборки в Gradle запускается несколько JVM процессов, одни процессы могут порождать другие. Можно сделать fork процессов и главное, чтобы все они использовали одни и те же аргументы JVM. С помощью GRADLE_OPTS добиться этого невозможно. Поэтому была придумана новая системная переменная JDK_JAVA_OPTIONS, которая используется всеми JVM процессами в Gradle (подробней о ней здесь). Более того, начиная со сборки b157 появилась системная переменная JDK_JAVAC_OPTIONS для передачи параметров в Java компилятор (javac). Установим JDK_JAVA_OPTIONS в следующее значение:

И перезапустим сборку. У нас выпало исключение:

Такой ошибки у нас еще не было. Суть ее в том, что мы хотим получить доступ к классам из JDK, которые находятся в пакетах, не указанных модулем как экспортируемых (exported) в module-info.java. Это можно обойти, если добавить в JAVA_JDK_OPTIONS «—add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED»

Теперь сборка прошла успешно. Запустим тесты: gradle test. Тесты посыпались с теми же ошибками, что и в Maven. Это можно исправить, просто указав аргументы JVM в блоке test:

Мы все еще используем source/target compatibility 1.8 в нашем проекте. Если мы поменяем их на 1.9, то при компиляции получим ошибку:

Все потому что мы перешли на 1.9, а значит должны оформлять наши проекты в модули, писать module-info.java и в них указать, чтобы нам нужен (requires) тот или иной модуль из JDK. Ситуация становится интересней для Maven/Gradle зависимостей. Здесь можно прочесть о том, как конфигурировать модули, если они содержат одинаковые пакеты.

Однако пока Gradle еще не полностью готов к Java 9, вы можете запускать его под Java 8, а компилировать проект под Java 9. Для этого нужно в скрипте сборки указать конфигурацию под версию:


Тестирование REST-контейнеров

Так как я в своем докладе рассказывал про REST-контейнеры и веб-сервера, то интересно будет их проверить на совместимость с Java 9, тем более что это достаточно сложные технологии.

Начнем с Ratpack. Это довольно новый сервер, полностью написанный на Java 8 и основанный на Netty. Если мы запустим его, то получим исключение:

Нам нужно лишь добавить модуль java.activation при старте сервера, чтобы это починить:

Теперь перейдем к Apache CXF. Для него нужно указать другой модуль:

Для запуска приложения с Jersey (JAX-RS) я использую Jetty сервер. Jersey тоже требует предыдущий модуль.

Я думаю, что вы знаете либо слышали, что летом этого года выходят Spring Framework 5 и Spring Boot 2.0, специально приуроченные к выходу JDK 9 и даже использующие некоторые ее возможности. Пока они не вышли, интересно проверить текущие версии (Spring Boot 1.5.3 и Spring Framework 4.3.8) на «запускаемость».

Spring Boot поддерживает три встроенных сервера: Tomcat, Jetty и Undertow. К сожалению, у меня не получилось запустить REST-приложение ни на одном из них. Оно просто зависало на стадии загрузки.

JMeter — одна из наиболее популярных утилит для тестирования веб-приложений. Она может работать как в консольном варианте, так и в режиме с UI. Готово ли оно к Java 9? Если мы возьмем последнюю версию (3.2) и запустим jmeter.bat, то увидим в консоли ошибку:

Это достаточно странное сообщение, которое судя по всему печатает не JVM. Если мы заглянем в исполняемый файл, то увидим целые блоки кода, где сначала выполняется команда «java-version», потом ее результат парсится и из него выделяется старшая и младшая версии. Причем JMeter предполагает, что результат будет в формате 1.8.0.

Так как в Java 9 результат уже в формате 9.0.0 (openjdk.java.net/jeps/223), то это приводит к катастрофическим последствиям и аварийному завершению приложения. Причем JMeter даже не пишет, что версия неправильная, а просто говорит, что не может найти Java.

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

Для того, чтобы избежать подобных ошибок, нужно лишь добавить в JVM аргументы в скрипте строку:

Заключение и спасительный флаг

Как вы видите, в последний год вендорами была проделана большая работа по обеспечению совместимости с Java 9. Это тем более было трудно, что даже в этом году были некоторые изменения в API JDK. Тем не менее многие библиотеки уже успешно работают над Java 9, некоторые без каких-либо ухищрений, некоторые с дополнительными аргументами для JVM.

Тем не менее, выяснять и разбираться в настройках не так приятно, поэтому в конце марта 2020 года руководство Oracle решило упростить жизнь разработчикам и добавить новый спасительный флаг, который упростит миграцию на Java 9, но будет удален в Java 10.

Этот флаг —permit-illegal-access разрешает доступ всем анонимным модулям через reflection к коду именованных модулей и позволяет не писать многочисленные —add-opens. Единственный минус этого флага — он будет выводить предупреждения в консоль обо всех случаях несанкционированного доступа.

Однако оказалось, что, хотя этот флаг и избавляет от необходимости указывать многочисленные —add-opens, он не избавляет от необходимости указывать самого себя. Поэтому начиная со сборки b172 его предполагается заменить на флаг —illegal-access. У этого флага будет четыре значения:

  • permit. Это значение по умолчанию, которое открывает доступ через reflection из всех анонимных модулей во все пакеты именованных модулей. При этом значении только один раз печатается предупреждение о попытке доступа.
  • warn. Каждая попытка получить доступ через reflection приводит к выводу предупреждения.
  • debug. Здесь к выводу предупреждения выводится еще и stacktrace операции.
  • deny. Планируется сделать дефолтным в Java 10. Запрещает доступ через reflection для всех пакетов в именованных модулях, кроме указанных явно в —add-opens.

Подробнее можно прочесть здесь. Интересно, что на момент сборки b173 этот флаг все еще не добавлен.

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

[Перевод] Руководство по Java 9 для тех, кому приходится работать с legacy-кодом

Раз в несколько лет, с выходом новой версии Java, докладчики на JavaOne начинают смаковать новые языковые конструкции и API, хвалить их достоинства. А ретивым разработчикам тем временем не терпится внедрить новые возможности. Такая картина далека от реальности – она совершенно не учитывает, что большинство программистов заняты поддержкой и доработкой уже существующих приложений, а не пишут новые приложения с нуля.

Большинство приложений – в особенности коммерческие — должны быть обратно совместимы с более ранними версиями Java, в которых не поддерживаются все эти новые супер-пупер возможности. Наконец, большинство заказчиков и конечных пользователей, особенно в сегменте больших предприятий, настороженно относятся к радикальному обновлению Java-платформы, предпочитая выждать, пока она окрепнет.

Поэтому, как только разработчик собирается попробовать новую возможность, он сталкивается с проблемами. Вы бы стали использовать у себя в коде методы интерфейсов по умолчанию? Возможно – если вы счастливчик, и вашему приложению не требуется взаимодействовать с Java 7 или ниже. Хотите использовать класс java.util.concurrent.ThreadLocalRandom для генерации псевдослучайных чисел в многопоточном приложении? Не выйдет, если ваше приложение должно работать одновременно на Java 6, 7, 8 или 9.

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


Итак, есть ли в новом релизе Java 9 что-нибудь для программистов, занятых поддержкой унаследованного кода? Что-то, способное облегчить им жизнь? К счастью — да.

Что приходилось делать при поддержке legacy-кода то появления Java 9

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

Например, можно применить позднее связывание, если вы хотите получить доступ к новому API, когда вашему приложению также требуется работать со старыми версиями Java, не поддерживающими этот API. Допустим, вам требуется использовать класс java.util.stream.LongStream , появившийся в Java 8, и вы хотите применить метод anyMatch(LongPredicate) этого класса, но приложение должно быть совместимо с Java 7. Можно создать вспомогательный класс, вот так:

Есть способы упростить эту операцию, либо сделать ее более общей, либо более эффективной – идею вы уловили.

Вместо того, чтобы вызывать theLongStream.anyMatch(thePredicate) , как вы поступили бы в Java 8, можно вызвать LongStreamHelper.anyMatch(theLongStream, thePredicate) в любой версии Java. Если вы имеете дело с Java 8 – это сработает, но, если с Java 7 – то программа выбросит исключение NotImplementedException .

Почему это некрасиво? Потому что код может чрезмерно усложниться, если требуется обращаться ко множеству API (на самом деле, даже сейчас, с единственным API, это уже неудобно). Кроме того, такая практика и не типобезопасна, поскольку в коде нельзя прямо упомянуть LongStream или LongPredicate . Наконец, такая практика гораздо менее эффективна, из-за издержек, связанных с рефлексией, а также из-за дополнительных блоков try-catch . Следовательно, хотя и можно так сделать, это не слишком интересно, и чревато ошибками по невнимательности.

Да, вы можете обращаться к новым API, а ваш код при этом сохраняет обратную совместимость, но с новыми языковыми конструкциями вам это не удастся. Например, допустим, что нам нужно использовать лямбда-выражения в коде, который должен оставаться обратно-совместимым и работать в Java 7. Вам не повезло. Компилятор Java не позволит указать версию исходного кода выше целевой. Так, если задать уровень соответствия исходного кода 1.8 (т.е., Java 8), а целевой уровень соответствия будет 1.7 (Java 7), то компилятор вам этого не позволит.

Вам помогут разноверсионные JAR-файлы

Сравнительно недавно появилась еще одна отличная возможность использовать новейшие возможности Java, позволяя при этом приложениям работать со старыми версиями Java, где такие приложения не поддерживались. В Java 9 такая возможность предоставляется как для новых API, так и для новых языковых конструкций Java: речь о разноверисонных JAR-файлах.

Разноверсионные JAR-файлы почти не отличаются от старых добрых JAR-файлов, но с одной важнейшей оговоркой: в новых JAR-файлах появилась своеобразная «ниша», куда можно записывать классы, использующие новейшие возможности Java 9. Если вы работаете с Java 9, то JVM найдет эту «нишу», станет использовать классы из нее и игнорировать одноименные классы из основной части JAR-файла.

Однако, при работе с Java 8 или ниже, JVM неизвестно о существовании этой «ниши». Она игнорирует ее и использует классы из основной части JAR-файла. С выходом Java 10 появится новая аналогичная «ниша» для классов, использующих наиболее актуальные возможности Java 10 и так далее.

В JEP 238 – предложении на доработку Java, где описаны ращновенсионные JAR-файлы, приводится простой пример. Допустим, у нас есть JAR-файл с четырьмя классами, работающими в Java 8 или ниже:

Теперь представим, что после выхода Java 9 мы переписываем классы A и B, чтобы они могли использовать новые возможности, специфичные для Java 9. Затем выходит Java 10, и мы вновь переписываем класс A, чтобы он мог использовать новые возможности Java 10. При этом, приложение по-прежнему должно нормально работать с Java 8. Новый разноверсионный JAR-файл выглядит так:

JAR-файл не только приобрел новую структуру; теперь в его манифесте указано, что этот файл разноверсионный.

Когда вы запускаете этот JAR-файл на Java 8 JVM, он игнорирует раздел META-INFVersions , поскольку даже не подозревает о нем и не ищет его. Используются лишь оригинальные классы A, B, C и D.

При запуске под Java 9, используются классы, находящиеся в META-INFVersions , причем, они используются вместо оригинальных классов A и B, но классы в META-INFVersions игнорируются.

При запуске под Java 10 используются обе ветки META-INFVersions ; в частности, версия A от Java 10, версия B от Java 9 и используемые по умолчанию версии C и D.

Итак, если в вашем приложении вам нужен новый ProcessBuilder API из Java 9, но нужно обеспечить, чтобы приложение продолжало работать и под Java 8, просто запишите в раздел META-INFVersions JAR-файла новые версии ваших классов, использующие ProcessBuilder, а старые классы оставьте в основной части архива, используемой по умолчанию. Именно так проще всего использовать новые возможности Java 9, не жертвуя при этом обратной совместимостью.

В Java 9 JDK есть версия инструмента jar.exe, поддерживающая создание разноверсионных JAR-файлов. Такую поддержку также обеспечивают и другие инструменты, не входящие в JDK.

Java 9: модули, повсюду модули

Система модулей Java 9, (также известная под названием Project Jigsaw) – это, несомненно, крупнейшее изменение в Java 9. Одна из целей модуляризации — усилить действующий в Java механизм инкапсуляции, чтобы разработчик мог указывать, какие API предоставляются другим компонентам и мог рассчитывать, что JVM будет навязывать инкапсуляцию. При модуляризации инкапсуляция получается сильнее, чем при применении модификаторов доступа public/protected/private у классов или членов классов.

Вторая цель модуляризации – указать, каким модулям необходимы для работы другие модули и еще до запуска приложения заблаговременно убедиться, что все необходимые модули на месте. В таком смысле модули сильнее традиционного механизма classpath, поскольку пути classpath заблаговременно не проверяются, и возможны ошибки из-за отсутствия необходимых классов. Таким образом, некорректный classpath может быть обнаружен уже тогда, когда приложение успеет проработать достаточно долго, либо после того, как оно будет много раз запущено.
Вся система модулей большая и сложная, и ее подробное обсуждение выходит за рамки этой статьи (Вот хорошее, подробное объяснение). Здесь я уделю внимание именно тем аспектам модуляризации, которые помогают разработчику при поддержке унаследованных приложений.

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

Мастер Йода рекомендует:  Достаточно задать один вопрос, чтобы понять, какой вы программист

Во-первых, JAR-файл становится модуляризован (и превращается в модуль) с появлением в нем файла module-info.class (скомпилированного из module-info.java) у корня файла JAR. module-info.java содержит метаданные, в частности, название модуля, пакеты которого экспортируются (т.e., становятся видны извне), каких модулей требует данный модуль и некоторая иная информация.

Информация в module-info.class видна лишь в случаях, когда JVM ищет ее – то есть, система трактует модуляризованные JAR-файлы точно как обычные, если работает со старыми версиями Java (предполагается, что код был скомпилирован для работы с более старой версией Java. Строго говоря, требуется немного похимичить, и все равно указывать в качестве целевой версии module-info.class именно Java 9, но это реально).

Таким образом, у вас должна остаться возможность запускать модуляризованные JAR-файлы с Java 8 и ниже при условии, что в иных отношениях они также совместимы с более ранними версиями Java. Также отметим, что файлы module-info.class можно, с оговорками, помещать в версионируемых областях разноверсионных JAR-файлов.


В Java 9 существует как classpath, так и путь к модулю. and a module path. Classpath работает как обычно. Если поставить модуляризованный JAR-файл в classpath, он тратуется как любой другой JAR-файл. То есть, если вы модуляризовали JAR-файл, а ваше приложение еще не готово обращаться с ним как с модулем, его можно поставить в classpath, он будет работать как всегда. Ваш унаследованный код должен вполне успешно с ним справиться.

Также отметим, что коллекция всех JAR-файлов в classpath считается частью единственного безымянного модуля. Такой модуль считается самым обычным, однако, всю информацию он экспортирует другим модулям, и может обращаться к любым другим модулям. Таким образом, если у вас еще нет модуляризованного Java-приложения, но есть некие старые библиотеки, которые тоже пока не модуляризованы (и, вероятно, никогда не будут) – можно просто положить все эти библиотеки в classpath, и вся система будет нормально работать.

В Java 9 есть путь к модулям, работающий наряду с classpath. При использовании модулей из этого пути JVM может проверять (как во время компиляции, так и во время выполнения), все ли необходимые модули на месте, и сообщать об ошибке, если каких-то модулей не хватает. Все JAR-файлы в classpath, как члены безымянного модуля, доступны модулям, перечисленным в модульном пути – и наоборот.

Не составляет труда перенести JAR-файл из classpath в путь модулей – и пользоваться всеми преимуществами модуляризации. Во-первых, можно добавить файл module-info.class в файл JAR, а затем поставить модуляризованный JAR-файл в путь модулей. Такой новоиспеченный модуль все равно сможет обращаться ко всем оставшимся JAR-файлам в classpath JAR, поскольку они входят в безымянный модуль и остаются в доступе.

Также возможно, что вы не хотите модуляризовать JAR-файл, либо, что JAR-файл принадлежит не вам, а кому-то еще, так что модуляризовать его сами вы не можете. В таком случае JAR-файл все равно можно поставить в путь модулей, он станет автоматическим модулем.

Автоматический модуль считается модулем, даже если в нем нет файла module-info.class . Этот модуль одноименен тому JAR-файлу, в котором содержится, и другие модули могут явно затребовать его. Он автоматически экспортирует все свои публично доступные API и читает (то есть, требует) все прочие именованные модули, а также безымянные модули.

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

Не каждый немодуляризованный JAR-файл можно переместить в путь модулей и превратить его в автоматический модуль. Существует правило: пакет может входить в состав всего одного именованного модуля. То есть, если пакет находится более чем в одном JAR-файле, то всего один JAR-файл с этим пакетом в составе можно превратить в автоматический модуль. Остальные могут остаться в classpath и войти в состав безымянного модуля.

На первый взгляд, описанный здесь механизм кажется сложным, но на практике он весьма прост. На самом деле, речь в данном случае лишь о том, что можно оставить старые JAR-файлы в classpath или переместить их в путь модулей. Можно разбить их на модули или не делать этого. А когда ваши старые JAR-файлы будут модуляризованы, можно оставить их в classpath или переместить в путь модулей.

В большинстве случаев все должно попросту работать, как и раньше. Ваши унаследованные JAR-файлы должны прижиться в новой модульной системе. Чем больше вы модуляризуете код, тем больше информации о зависимостях требуется проверять, а недостающие модули и API будут обнаруживаться на гораздо более ранних этапах разработки и, возможно, избавят вас от больших кусков работы.

Java 9 «делает сама»: Модульный JDK и Jlink

Одна из проблем с унаследованными Java-приложениями заключается в том, что конечный пользователь может не работать с подходящей средой Java. Один из способов гарантировать работоспособность Java-приложения – предоставить среду выполнения вместе с приложением. Java позволяет создавать приватные (многократно распространяемые) JRE, которые можно распространять в пределах приложения. Здесь рассказано, как создать приватную JRE. Как правило, берется иерархия файлов JRE, устанавливаемая вместе с JDK, нужные файлы сохраняются, а также сохраняются опциональные файлы с тем функционалом, который может понадобиться в вашем приложении.

Процесс немного хлопотный: необходимо поддерживать иерархию установочных файлов, быть при этом внимательным, поэтому вы не пропускаете ни одного файла, ни одного каталога. Само по себе это не повредит, однако, все-таки хочется избавиться от всего лишнего, поскольку эти файлы занимают место. Да, легко поддаться и совершить такую ошибку.

Так что почему бы не перепоручить эту работу JDK?

В Java 9 можно создать самодостаточную среду, добавляемую к приложению – и в этой среде будет все необходимое для работы приложения. Больше не придется волноваться, что на пользовательском компьютере окажется не та среда для выполнения Java, не придется беспокоиться о том, что вы сами неправильно собрали приватную JRE.

Ключевой ресурс для создания таких самодостаточных исполняемых образов – это модульная система. Модуляризовать теперь можно не только собственный код, но и сам Java 9 JDK. Теперь библиотека классов Java – это коллекция модулей, из модулей же состоят и инструменты JDK. Система модулей требует указывать модули базовых классов, которые необходимы в вашем коде, и при этом вы указываете необходимые элементы JDK.

Чтобы собрать все это вместе, в Java 9 предусмотрен специальный новый инструмент под названием jlink. Запустив jlink, вы получаете иерархию файлов – именно тех, что нужны для запуска вашего приложения, ни больше, ни меньше. Такой набор будет гораздо меньше стандартной JRE, причем, он будет платформо-специфичным (то есть, подбираться для конкретной операционной системы и машины). Поэтому, если вы захотите создать такие исполняемые образы для других платформ, потребуется запустить jlink в контексте установки на каждой конкретной платформе, для которой вам нужен такой образ.

Также обратите внимание: если запустить jlink с приложением, в котором ничего не модуляризовано, у инструмента просто не будет нужной информации, позволяющей ужать JRE, поэтому jlink ничего не останется, кроме как упаковать целую JRE. Даже в таком случае вам будет немного удобнее: jlink сам упакует для вас JRE, поэтому можете не волноваться о том, как правильно скопировать файловую иерархию.

С jlink становится легко упаковать приложение и все, что необходимо для его запуска – и можете не волноваться, что сделаете что-нибудь неправильно. Инструмент упакует только ту часть среды исполнения, которая требуется для работы приложения. То есть, унаследованное Java-приложение гарантированно получит такую среду, в которой оно окажется работоспособным.

Встреча старого и нового

Одна из проблем, возникающих при поддержке унаследованного Java-приложения заключается в том, что вы оказываетесь лишены всех плюшек, появляющихся при выходе новой версии. В Java 9, как и в предшествующих версиях, появилась целая куча великолепных новых API и языковых возможностей, но разработчики (наученные горьким опытом) могут предположить, что попросту не смогут ими воспользоваться, не нарушив обратной совместимости с более ранними версиями Java.

Следует отдать должное проектировщикам Java 9: по-видимому, они это учли и хорошо поработали, чтобы предоставить эти новые возможности и тем разработчикам, которым приходится поддерживать старые версии Java.

Разноверсионные JAR-файлы позволяют разработчикам применять новые возможности Java 9 и выносить их в отдельную часть JAR-файла, где более ранние версии Java их не заметят. Таким образом, разработчику легко писать код для Java 9, оставить старый код для Java 8 и ниже и предоставить среде исполнения выбор – какие классы она сможет запустить.

Благодаря модулям Java, разработчику проще проверять зависимости, достаточно писать все новые JAR-файлы в модульном виде, а старый код оставлять немодуляризованным. Система очень щадящая, она ориентирована на постепенную миграцию и практически всегда поддерживает работу с унаследованным кодом, который «слыхом не слыхивал» о модульной системе.

Благодаря модульному JDK и jlink, можно с легкостью создавать исполняемые образы и гарантированно обеспечивать приложение такой средой исполнения, в которой будет все необходимое для работы. Ранее такой процесс был чреват множеством ошибок, но современный инструментарий Java позволяет его автоматизировать – и все просто работает.

В отличие от предыдущих релизов Java, в Java 9 вы можете свободно пользоваться всеми новыми возможностями, а если имеете дело со старым приложением и должны гарантировать его поддержку – то сможете удовлетворить потребности всех ваших пользователей, независимо от того, горят ли они желанием обновляться до самой актуальной версии Java.

сравнение Поддерживает ли система модуля Java 9 необязательные зависимости?


java 9 модульность пример (1)

Фон

В maven артефакт может объявить зависимость с

Это означает, что зависимость не требуется, но может использоваться, если она есть.

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

Вопросы

  • Действительно ли модульная система Java 9 не поддерживает необязательные зависимости?
  • Почему бы и нет?
  • Какие альтернативы необязательным зависимостям предоставляет модульная система Java 9?

Случай использования

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

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

Расширьте язык объявлений модулей, чтобы позволить использовать static модификатор в директиве require со следующими значениями:

Во время компиляции requires static M выражающий обязательную зависимость. Это ошибка, если подходящий модуль не может быть найден среди наблюдаемых модулей и разрешен.

В фазах после времени компиляции requires static M выражающий необязательную зависимость. Система модулей не будет искать наблюдаемые модули для подходящего модуля во время разрешения, но если итоговый граф модулей содержит подходящий модуль, то он добавит соответствующий край читаемости перед выполнением обычных проверок работоспособности после разрешения. [. ]

Таким образом, гипотетический модуль декларации вида

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

Я написал демо для этого. Интересные лакомые кусочки — это module-info.java модуля, объявляющего необязательные зависимости .

. и код в том же модуле, который хочет получить доступ к типам из его необязательных зависимостей. Он должен быть написан так, чтобы он не работал, если типы ChocolateFactory и / или QuoteFactory отсутствуют:

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

Конечно, также возможно, что другие модули требуют их необязательно, что вынуждает JVM включать их в граф модулей.

Как Java 9 модулей решить проблемы, связанные с зависимостями переходными?

Я читал, что Java 9 модулей помогает решать проблемы, которые появляются при трогании несколько версий одного и того же зависимость из-за переходных зависимостей. Я не могу понять, почему. Если вы принесете несколько модулей, которые вы можете получить и ту же проблему. Я имею в виду, если один из модулей приносит в одной Hamcrest версии и другие приносят другие тестовые инструменты, вводящие версии 2, 3, 4 или любой из Mockito или JUnit. Как модули помогает с этим вопросом?

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

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

Поддерживает ли система Java 9 Module дополнительные зависимости?

В maven артефакт может объявлять зависимость с

что означает, что зависимость не требуется, но может быть использована, если она присутствует.

Мастер Йода рекомендует:  Как использовать базу данных MySQL в Java


The State of the Module System seems to specify that a module can only read modules it has required.

Вопросы

  • Система Java 9 действительно не поддерживает дополнительные зависимости?
  • Почему бы и нет?
  • Какие альтернативы факультативным зависимостям предоставляет система модуля Java 9?

Использовать случай

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

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

Java 9 наконец-то разберется с зависимостями

Перед началом перехода с Java 8 на Java 11 или на более позднюю версию, первый вопрос, на который необходимо ответить — можете ли вы реализовать переход одним махом или вам необходимо провести его в течение длительного промежутка времени

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

Если же вы не хотите изменять требования к минимальной версии Java или ваш проект слишком большой, мы рекомендуем следующий подход:

  • Не создавайте отдельную долговременную ветку для перехода — вместо этого делайте это в регулярной ветке развития. Таким образом, вы не столкнетесь с конфликтами при слиянии и можете быть уверены, что изменения ваших коллег также построены на Java 11
  • Настройте ваш сервер непрерывной интеграции для запуска сборок проекта как в своей общей конфигурации, так и на Java 11
  • Изучите, как ваша система сборки может поддерживать различные конфигурации, зависящие от версии Java (в Maven для этого используются профайлы). Таким образом, вы можете сохранить старую версию сборки, добавив одновременно конфигурацию, которая использует новую версию
  • Постарайтесь сократить изменения в конфигурации, зависящие от версии Java до минимума

Таким образом, вы можете гарантировать, что ваш проект работает и на Java 8 и на Java 11 (или более поздней версии). Если вы захотите работать с двумя (или более) версиями Java, то сможете быстро переключать профайлы и работать с ними. А когда вы совсем перестанете использовать Java 8, то не забудьте объединить версии конфигурации, чтобы уменьшить сложность проекта

Первое правило перехода на Java 11 — обновить все: вашу IDE, систему сборки, ее плагины и, самое главное, ваши зависимости. Вам не обязательно делать все эти обновления заранее, но если вы это можете, то вы должны так сделать — это, скорее всего, поможет вам преодолеть некоторые препятствия, относительно которых вы останетесь в блаженном неведении

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

  • IntelliJ IDEA: 2020.2
  • Eclipse: Photon 4.9RC2 with Java 11 plugin
  • Maven: 3.5.0
    • compiler plugin: 3.8.0
    • surefire and failsafe : 2.22.0
  • Gradle: bl ocked by #5120

Некоторые зависимости, которые вы должны отслеживать (а также версии, которые, как известно, работают на Java 11):

  • Все, что использует для работы байт-код, например ASM (7.0), Byte Buddy (1.9.0), cglib (3.2.8) или Javassist (3.23.1-GA). Начиная с Java 9, модификации байт-кода происходят каждые шесть месяцев, поэтому вам придется регулярно обновлять такие библиотеки
  • Все, что использует то, что работает с байт-кодом, например Spring (5.1), Hibernate (неизвестно), Mockito (2.20.0) и многие, многие другие проекты

Второй совет слишком общий и не очень-то помогает, но это печальная правда: многие мощные проекты работают с байт-кодом под капотом. Это помогает развить подход к выявлению проблем, связанных с этим

Вот некоторые советы — обращайте внимание в логах на:

  • трассировки стеков, которые заканчиваются вызовом библиотек, использующих байт-коды
  • ошибки или предупреждения, которые жалуются на уровень байт-кода
  • ошибки или предупреждения, которые бормочут о «unknown (constant pool) entries»

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

Например, для более старой версией Hibernate необходимо было обновить Javassist для работы с Java 11:

Готовимся к Java 9. Обзор самых интересных улучшений


В эту среду, 30 августа, в офисе компании Oracle состоялась встреча JUG.ru с Олегом Шелаевым, Developer Advocate в компании ZeroTurnaround, которая делает JRebel и XRebel. Тема встречи — инструменты создания многопоточных программ на Java (от конструирования велосипедов и запуска потоков ручками, до ForkJoinPool-ов, зеленых потоков и транзакционной памяти).

Конечно, мы поинтересовались, какие фишки Java 9 считают в Zero Turnaround наиболее полезными. В результате, разжились статьей, которую вы сейчас читаете.

Мы долго ждали Java 9, и вот, релиз уже не за горами. Ура! Это был не самый простой путь, но тем не менее, даже самые жаркие споры о системе модулей потихоньку продвигаются вперед, и большинство участников приходят к согласию. Скорей всего, релиз состоится совсем скоро, например, 21 сентября 2020 года.

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

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

Запускай JShell, я подожду… готов? Нет еще? Окей… сделал? Все еще нет? Да, на разгорев нужно время… ок, запустилось, отлично! Начинаем.

Фабричные методы для коллекций

Одна из наиболее ожидаемых фишек Java 9 — возможность делать литералы коллекций, чтобы удобней записывать самые простые случаи. Шутка, конечно, мы же говорим о Java, литералов у нас нет, есть только статические фабричные методы. Тем не менее, теперь мы можем легко создавать List , Map и Set , используя готовые методы:

Это стало возможным благодаря появлению статических методов в интерфейсах (Java 8), использовать которые научились List , Map и Set .

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

Стримы

В Stream API добавили парочку очень полезных возможностей. В частности, методы dropWhile и takeWhile . Как можно предположить по названию, dropWhile выбрасывает элементы с начала и до тех пор, пока не будет выполнено условие, а takeWhile — забирает элементы вплоть до выполнения условия.

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

Если вам вдруг хотелось делать вычисления с фиксированной точкой на стримах, эта мечта может исполниться в Java 9.

Optional

Если вдруг кто не помнит, как их использовать, у нас есть отличная шпаргалка. В Java 9 наконец-то добавили метод or() , позволяющий в одну строчку связывать разные Optional’ы, не опускаясь до постоянных проверок на isPresent() .

Следующее хорошее дополнение — возможность преобразовывать Optional в стрим, содержащий не более одного элемента. Это реально полезно, если хочется использовать ленивые стримы. В примере ниже можно увидеть разницу своими глазами. Если вызвать map() на Optional, маппинг произойдет мгновенно, а вот на стриме — нет.

И наконец, у нас появился метод ifPresentOrElse . В Java 8, можно было определить поведение только для случая, когда значение Optional существует. В Java 9 стало возможно указать два разных Runnable, определяющих что делать, если значение существует, и если не существует.

Completable future

Еще одним кусочком API, который хорошенько заполировали, оказался класс CompletableFuture . В него добавили парочку отличных вещей, позволяющих писать еще более корректный многопоточный код.

Один из самых крутых методов — это copy() , который возвращает немутабельную копию этого CompletableFuture . В следующем примере, мы создаем CompletableFuture , делаем его копию и проверяем, что завершение копии не влияет на исходный объект. Это очень-очень полезно, когда создается асинхронный API, возвращающий CompletableFuture . Раньше нужно было знатно помучиться, обруливая ситуации, когда клиент может сам завершить CompletableFuture , возвращенное из такого API. Сейчас достаточно просто взывать метод copy() .

Но самое крутое в том, что остановка родителя распространяется на все копии!

Кроме того, наконец-то в них добавили таймауты. Работа с асинхронным API, без наличия встроенных функций работы с таймаутами, была весьма напряжной. В Java 9 стало возможным точно определять способ завершения CompletableFuture , после истечения вручную заданного промежутка времени.

API управления процессами

До Java 9, управление процессами было совершено не таким кроссплатформенным, как хотелось бы верить. Работа с подпроцессами раньше была несколько кривой, и вот в Java 9 её наконец выпрямили. Java 9 добавляет класс ProcessHandle , который предоставляет API для анализа текущего процесса, других процессов, найденных по пиду, их дочерних процессов, и так далее. Просто посмотрите на пример:

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

Еще одна популярная задача, которую будет куда удобней делать в Java 9 — запуск кода сразу после того, как процесс завершился. Java 9 предлагает для этого воспользоваться новым методом:


Указываете, что же вы хотите сделать, и это просто работает. Нет больше слёзок и нестабильных чужих библиотек.

StackWalker

Возрадуйтесь, ненавистники исключений! Теперь можно работать со стектрейсами, не создавая объектов Exception . Добро пожаловать в StackWalker !

StackWalker дает возможность бродить по стеку, фильтровать его, и эффективно делать разные другие вещи. Этот пример выдернет верхние 5 элементов из стектрейса:

Улучшения в языке Java

Улучшаются не только API, но и сам язык. Во-первых, символ _ (подчёркивание) больше не является корректным идентификатором. Если вы зачем-то его используете, придется перейти на двойное подчеркивание! (Подсказка: не делайте этого).

Это для того, чтобы в будущем можно было заменять на подчеркивание ненужные (опциональные) параметры при вызове функции.

Интерфейсы тоже немного доработали. Интерфейсы в Java 9 смогут содержать приватные методы. В Java 8 мы получили возможность хранить некую общую логику в default-методах. Теперь мы сможем выделять общую логику и внутри интерфейсов, без необходимости создания вспомогательных классов.

Вот вам небольшой синтетический пример:
jshell> interface A < private int zero() < return 0;>default int one() < return zero() + 1;>>
| created interface A

Ну и наконец, последнее новшество. Теперь можно использовать effectively final переменные в блоках try-with-resources. Это упрощает код, не нужно больше объявлять переменные внутри try . Просто работаете с ними в блоке try , и это компилируется.

После выполнения блока try , все упомянутые там AutoClosable закономерно закроются.

Заключение

Ура! Мы рассмотрели кучу всего, и это далеко не все новшества, появившиеся в Java 9. Тем не менее, перечисленные выше вещи кажутся нам наиболее полезными, и пользоваться ими будут при первой возможности.

Выпуск Java 9 готовится уже довольно давно, и всем нам пора хорошенько разобраться, как она на нас повлияет. Сейчас это уместно как никогда, учитывая, что режим работы с clasthpath останется неизменным, и переход на Java 9 может оказаться простым и безболезненным. Можно прямо сейчас скачать готовую сборку Java 9, разобраться с новыми API, распробовать их, и приготовиться к наступающему светлому будущему!

Авторы

Олег Шелаев — Java-разработчик и Developer Advocate в ZeroTurnaround. Когда не занимается написанием java agent-ов или тестов, пишет в блог RebelLabs или выступает на конференциях. В свободное время пытается продвигать науку в Тартуском университете, изучая проблемы динамических обновлений программ.

Программа читает из консоли и выводит обратно до тех пор, пока не будет введено stop-word

Всем доброго времени суток!

Java вижу впервые. Есть несколько заданий, но просить написать за меня — не позволяет совесть,а гуглить не умею. Потому спрошу, спрашивать не зазорно Нужен пинок для понимания

Задание такое: В консоли задаётся stop-word. Программа читает из консоли и выводит обратно до тех пор, пока не будет введено stop-word.

Подскажите, пожалуйста, как это грамотно реализовать. Ничего нагуглить нормального не смог

10.09.2014, 23:24

Запрашивать числа до тех пор, пока не будет введено первое число кратное 7, и вычислить сумму введенных чисел
Помогите решить Циклы с постусловием: Составьте программу которая будет запрашивать числа до тех.

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

Вводить строки до тех пор, пока не будет введено стоп-слово
Задача: вводить строки до тех пор, пока не стоп-слово. Моё минимально нерабочее решение: .

Ввод чисел до тех пор, пока не будет введено четное число
Составить процедуру, запрашивающую ввод чисел до тех пор, пока не будет введено четное число.

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

Добавить комментарий