«1. Обзор
Java 9 поставляется с богатым набором функций. Хотя новых языковых концепций нет, новые API и диагностические команды определенно будут интересны разработчикам.
В этом обзоре мы кратко рассмотрим некоторые новые функции; Полный список новых функций доступен здесь.
2. Модульная система — проект Jigsaw
Начнем с большого — внедрения модульности в платформу Java.
Модульная система предоставляет возможности, аналогичные системе фреймворка OSGi. Модули имеют концепцию зависимостей, могут экспортировать общедоступный API и сохранять детали реализации скрытыми/приватными.
Одним из основных мотивов здесь является предоставление модульной JVM, которая может работать на устройствах с гораздо меньшим объемом доступной памяти. JVM может работать только с теми модулями и API, которые требуются приложению. По этой ссылке вы найдете описание этих модулей.
Кроме того, внутренние API-интерфейсы JVM (реализации), такие как com.sun.*, больше недоступны из кода приложения.
Проще говоря, модули будут описаны в файле с именем module-info.java, расположенном в верхней части иерархии кода Java: умение обращаться.
module com.baeldung.java9.modules.car {
requires com.baeldung.java9.modules.engines;
exports com.baeldung.java9.modules.car.handling;
}
Более подробный пример см. в OpenJDK Project Jigsaw: Краткое руководство по модульной системе.
3. Новый HTTP-клиент
Долгожданная замена старого HttpURLConnection.
Новый API находится в пакете java.net.http.
Он должен поддерживать как протокол HTTP/2, так и рукопожатие WebSocket, с производительностью, сравнимой с Apache HttpClient, Netty и Jetty.
Давайте посмотрим на эту новую функциональность, создав и отправив простой HTTP-запрос.
Обновление: HTTP-клиент JEP перемещается в модуль инкубатора, поэтому он больше не доступен в пакете java.net.http и вместо этого доступен в jdk.incubator.http.
3.1. Быстрый запрос GET
В API используется шаблон Builder, что делает его действительно простым для быстрого использования:
4. API процессов
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());
API процессов был улучшен для контроля и управления процессами операционной системы.
4.1. Информация о процессе
Класс java.lang.ProcessHandle содержит большинство новых функций:
Текущий метод возвращает объект, представляющий процесс запущенной в данный момент JVM. Подкласс Info предоставляет подробную информацию о процессе.
ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();
Optional<String[]> args = procInfo.arguments();
Optional<String> cmd = procInfo.commandLine();
Optional<Instant> startTime = procInfo.startInstant();
Optional<Duration> cpuUsage = procInfo.totalCpuDuration();
4.2. Уничтожение процессов
Теперь давайте остановим все запущенные дочерние процессы с помощью destroy():
5. Небольшие языковые модификации
childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});
5.1. Try-With-Resources
В Java 7 синтаксис try-with-resources требует объявления новой переменной для каждого ресурса, управляемого оператором.
В Java 9 есть дополнительное уточнение: если на ресурс ссылается конечная или фактически конечная переменная, оператор try-with-resources может управлять ресурсом без объявления новой переменной:
5.2 . Расширение оператора Diamond
MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
// do some stuff with mac
}
try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
// do some stuff with finalCloseable
} catch (Exception ex) { }
Теперь мы можем использовать оператор Diamond в сочетании с анонимными внутренними классами:
5.3. Частный метод интерфейса
FooClass<Integer> fc = new FooClass<>(1) { // anonymous inner class
};
FooClass<? extends Integer> fc0 = new FooClass<>(1) {
// anonymous inner class
};
FooClass<?> fc1 = new FooClass<>(1) { // anonymous inner class
};
Интерфейсы в следующей версии JVM могут иметь частные методы, которые можно использовать для разделения длинных методов по умолчанию:
6. Инструмент командной строки JShell
interface InterfaceWithPrivateMethods {
private static String staticPrivate() {
return "static private";
}
private String instancePrivate() {
return "instance private";
}
default void check() {
String result = staticPrivate();
InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() {
// anonymous class
};
result = pvt.instancePrivate();
}
}}
JShell читается — оценивается — цикл печати — REPL для краткости.
Проще говоря, это интерактивный инструмент для оценки объявлений, операторов и выражений Java вместе с API. Это очень удобно для тестирования небольших фрагментов кода, которые в противном случае требуют создания нового класса с основным методом.
Сам исполняемый файл jshell находится в папке \u003cJAVA_HOME\u003e/bin:
Интерактивная оболочка поставляется с историей и автодополнением; он также предоставляет функциональные возможности, такие как сохранение и загрузка из файлов, всех или некоторых письменных операторов:
jdk-9\bin>jshell.exe
| Welcome to JShell -- Version 9
| For an introduction type: /help intro
jshell> "This is my long string. I want a part of it".substring(8,19);
$5 ==> "my long string"
Фрагменты кода выполняются при загрузке файла.
jshell> /save c:\develop\JShell_hello_world.txt
jshell> /open c:\develop\JShell_hello_world.txt
Hello JShell!
7. Подкоманды JCMD
«Давайте рассмотрим некоторые новые подкоманды в утилите командной строки jcmd. Мы получим список всех классов, загруженных в JVM, и их структуру наследования.
В приведенном ниже примере мы видим иерархию java.lang.Socket, загруженную в JVM, на которой работает Eclipse Neon:
Первый параметр команды jcmd — это идентификатор процесса (PID) JVM, на котором мы хотите запустить команду.
jdk-9\bin>jcmd 14056 VM.class_hierarchy -i -s java.net.Socket
14056:
java.lang.Object/null
|--java.net.Socket/null
| implements java.io.Closeable/null (declared intf)
| implements java.lang.AutoCloseable/null (inherited intf)
| |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket
| | implements java.lang.AutoCloseable/null (inherited intf)
| | implements java.io.Closeable/null (inherited intf)
| |--javax.net.ssl.SSLSocket/null
| | implements java.lang.AutoCloseable/null (inherited intf)
| | implements java.io.Closeable/null (inherited intf)
Другая интересная подкоманда — set_vmflag. Мы можем изменить некоторые параметры JVM онлайн, без необходимости перезапуска процесса JVM и изменения его параметров запуска.
Узнать все доступные флаги ВМ можно с помощью подкоманды jcmd 14056 VM.flags -all
8. API изображений с разным разрешением
Интерфейс java.awt.image.MultiResolutionImage инкапсулирует набор образов с разными решения в один объект. Мы можем получить вариант изображения для конкретного разрешения на основе заданной метрики DPI и набора преобразований изображения или получить все варианты изображения.
Класс java.awt.Graphics получает вариант из изображения с несколькими разрешениями на основе текущей метрики DPI дисплея и любых примененных преобразований.
Класс java.awt.image.BaseMultiResolutionImage обеспечивает базовую реализацию:
9. Обработчики переменных
BufferedImage[] resolutionVariants = ....
MultiResolutionImage bmrImage
= new BaseMultiResolutionImage(baseIndex, resolutionVariants);
Image testRVImage = bmrImage.getResolutionVariant(16, 16);
assertSame("Images should be the same", testRVImage, resolutionVariants[3]);
API находится в java.lang.invoke и состоит из VarHandle и MethodHandles. Он предоставляет эквиваленты операций java.util.concurrent.atomic и sun.misc.Unsafe для полей объекта и элементов массива с аналогичной производительностью.
В модульной системе Java 9 доступ к sun.misc.Unsafe из кода приложения будет невозможен.
10. Структура публикации-подписки
Класс java.util.concurrent.Flow предоставляет интерфейсы, поддерживающие структуру публикации-подписки Reactive Streams. Эти интерфейсы поддерживают взаимодействие между несколькими асинхронными системами, работающими на JVM.
Мы можем использовать служебный класс SubmissionPublisher для создания пользовательских компонентов.
11. Унифицированное ведение журнала JVM
Эта функция вводит общую систему ведения журнала для всех компонентов JVM. Он предоставляет инфраструктуру для ведения журналов, но не добавляет фактические вызовы журналов из всех компонентов JVM. Он также не добавляет журналирование в код Java в JDK.
Фреймворк ведения журнала определяет набор тегов, например, gc, компилятор, потоки и т. д. Мы можем использовать параметр командной строки -Xlog, чтобы включить ведение журнала во время запуска.
Давайте запишем сообщения, помеченные тегом «gc», используя уровень «debug» в файл с именем «gc.txt» без оформления:
-Xlog:help выведет возможные варианты и примеры. Конфигурация ведения журнала может быть изменена во время выполнения с помощью команды jcmd. Мы установим журналы сборщика мусора в информацию и перенаправим их в файл – gc_logs:
java -Xlog:gc=debug:file=gc.txt:none ...
12. Новые API
jcmd 9615 VM.log output=gc_logs what=gc
12.1. Immutable Set
java.util.Set.of() — создает неизменяемый набор заданных элементов. В Java 8 для создания набора из нескольких элементов потребовалось бы несколько строк кода. Теперь мы можем сделать это так же просто, как:
Set, возвращаемый этим методом, является внутренним классом JVM: java.util.ImmutableCollections.SetN, который расширяет общедоступный java.util.AbstractSet. Он неизменен — если мы попытаемся добавить или удалить элементы, будет выброшено исключение UnsupportedOperationException.
Set<String> strKeySet = Set.of("key1", "key2", "key3");
Вы также можете преобразовать весь массив в набор тем же методом.
12.2. Необязательный для Stream
java.util.Optional.stream() дает нам простой способ использования возможностей Streams для необязательных элементов:
13. Заключение
List<String> filteredList = listOfOptionals.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
Java 9 будет поставляться с модульным JVM и множество других новых и разнообразных улучшений и функций.
Вы можете найти исходный код примеров на GitHub.
«