1. Обзор
Java 9 поставляется с богатым набором функций. Хотя новых языковых концепций нет, новые API и диагностические команды определенно будут интересны разработчикам.
В этом обзоре мы кратко рассмотрим некоторые новые функции; полный список новых функций доступен здесь .
2. Модульная система — Проект Jigsaw
Давайте начнем с большого — внедрения модульности в платформу Java.
Модульная система предоставляет возможности, аналогичные системе платформы OSGi. Модули имеют концепцию зависимостей, могут экспортировать общедоступный API и сохранять детали реализации скрытыми/приватными.
Одним из основных мотивов здесь является предоставление модульной JVM, которая может работать на устройствах с гораздо меньшим объемом доступной памяти. JVM может работать только с теми модулями и API, которые требуются приложению. По этой ссылке вы найдете описание этих модулей.
Кроме того, внутренние API-интерфейсы JVM (реализации), такие как com.sun.*
, больше недоступны из кода приложения.
Проще говоря, модули будут описаны в файле с именем module-info.java,
расположенном в верхней части иерархии кода Java:
module com.foreach.java9.modules.car {
requires com.foreach.java9.modules.engines;
exports com.foreach.java9.modules.car.handling;
}
Наш модуль car
требует запуска модуля модуля
и экспортирует пакет для обработки
.
Более подробный пример см. в OpenJDK Project Jigsaw: Module System Quick-Start Guide .
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, что делает его очень простым для быстрого использования:
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://postman-echo.com/get"))
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandler.asString());
4. Процесс API
API процесса был улучшен для контроля и управления процессами операционной системы.
4.1. Обрабатывать информацию
Класс java.lang.ProcessHandle
содержит большинство новых функций:
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();
Текущий метод возвращает объект, представляющий процесс запущенной в данный момент JVM .
Подкласс Info
предоставляет подробную информацию о процессе.
4.2. Уничтожение процессов
Теперь давайте остановим все запущенные дочерние процессы с помощью destroy()
:
childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});
5. Небольшие языковые модификации
5.1. Попробуйте с ресурсами
В Java 7 синтаксис try-with-resources
требует объявления новой переменной для каждого ресурса, управляемого оператором.
В Java 9 есть дополнительное уточнение: если на ресурс ссылается конечная или фактически конечная переменная, оператор try-with-resources может управлять ресурсом без объявления новой переменной:
MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
// do some stuff with mac
}
try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
// do some stuff with finalCloseable
} catch (Exception ex) { }
5.2. Расширение оператора Diamond
Теперь мы можем использовать оператор алмаза в сочетании с анонимными внутренними классами:
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
};
5.3. Частный метод интерфейса
Интерфейсы в будущей версии JVM могут иметь частные
методы, которые можно использовать для разделения длинных методов по умолчанию:
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();
}
}}
6. Инструмент командной строки JShell
JShell — это цикл чтения-оценки-печати — REPL для краткости.
Проще говоря, это интерактивный инструмент для оценки объявлений, операторов и выражений Java вместе с API. Это очень удобно для тестирования небольших фрагментов кода, которые в противном случае требуют создания нового класса с основным
методом.
Сам исполняемый файл jshell
можно найти в папке <JAVA_HOME>/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:
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)
Первый параметр команды jcmd
— это идентификатор процесса (PID) JVM, на которой мы хотим запустить команду.
Еще одна интересная подкоманда — set_vmflag
. Мы можем изменить некоторые параметры JVM онлайн, без необходимости перезапуска процесса JVM и изменения его параметров запуска.
Узнать все доступные флаги ВМ можно с помощью подкоманды jcmd 14056 VM.flags -all
8. API изображений с несколькими разрешениями
Интерфейс java.awt.image.MultiResolutionImage
инкапсулирует набор изображений с разным разрешением в один объект. Мы можем получить вариант изображения для конкретного разрешения на основе заданной метрики DPI и набора преобразований изображения или получить все варианты изображения.
Класс java.awt.Graphics
получает вариант изображения с несколькими разрешениями на основе текущей метрики DPI дисплея и любых примененных преобразований.
Класс java.awt.image.BaseMultiResolutionImage
обеспечивает базовую реализацию:
BufferedImage[] resolutionVariants = ....
MultiResolutionImage bmrImage
= new BaseMultiResolutionImage(baseIndex, resolutionVariants);
Image testRVImage = bmrImage.getResolutionVariant(16, 16);
assertSame("Images should be the same", testRVImage, resolutionVariants[3]);
9. Переменные дескрипторы
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» без каких-либо украшений:
java -Xlog:gc=debug:file=gc.txt:none ...
-Xlog:help
выведет возможные варианты и примеры. Конфигурация ведения журнала может быть изменена во время выполнения с помощью команды jcmd
. Мы собираемся установить журналы GC в информацию и перенаправить их в файл — gc_logs:
jcmd 9615 VM.log output=gc_logs what=gc
12. Новые API
12.1. Неизменяемый набор
java.util.Set.of()
— создает неизменяемый набор заданных элементов. В Java 8 для создания набора из нескольких элементов потребовалось бы несколько строк кода. Теперь мы можем сделать это так же просто, как:
Set<String> strKeySet = Set.of("key1", "key2", "key3");
Набор ,
возвращаемый этим методом, является внутренним классом JVM: java.util.ImmutableCollections.SetN
, который расширяет общедоступный java.util.AbstractSet
. Он неизменен — если мы попытаемся добавить или удалить элементы, будет выброшено исключение UnsupportedOperationException .
Вы также можете преобразовать весь массив в набор
тем же методом.
12.2. Необязательно для потоковой передачи
java.util.Optional.stream()
дает нам простой способ использовать возможности потоков для необязательных элементов:
List<String> filteredList = listOfOptionals.stream()
.flatMap(Optional::stream)
.collect(Collectors.toList());
13. Заключение
Java 9 будет поставляться с модульной JVM и множеством других новых и разнообразных улучшений и функций.
Вы можете найти исходный код примеров на GitHub .