Это раньше разработчики ждали новой Java по нескольку лет, кто — с ужасом, а кто и с надеждой. Времена изменились, и новые версии JDK будут радовать нас раз в полгода. Если вам пока неясно, к чему это приведёт, ознакомьтесь с мнением эксперта, а здесь мы перечислим основные изменения в Java 10 — самой новой версии нашего с вами любимого языка. Новая Java… Опять… Встречаем Java 10 - 1В квадратных скобках перед новой «фичей» указан номер JEP, то есть, «JDK Enchancement Proposal». JEP — это предложение по улучшению OpenJDK, которое могут утвердить, отложить или отклонить. То есть, по сути, сборник JEP’ов — стратегия развития OpenJDK.

Важные фичи Java 10

[286] Local-Variable Type Inference — предложение по введению в Java ключевого слова var, что избавляет от необходимости указывать тип локальной переменной явно. То есть теперь вы можете не указывать тип проинициализированной переменной, а писать что-то вроде:
var list = new ArrayList<String>();  //перед нами ArrayList<String>
var stream = list.stream();          // перед нами Stream<String>
Это устраняет дублирование определения типа ArrayList <String>, которое нам пришлось бы использовать раньше. Интересно отметить, что var не становится ключевым словом, а является зарезервированным типом. То есть вы можете использовать var в качестве имени переменной, метода или пакета. А вот назвать так класс вы не сможете (какая потеря!). [296] Объединение «леса» JDK в единый репозиторий. В JDK 9 есть восемь репозиториев — root, corba, hotspot, jaxp, jaxws, jdk, langtools, nashorn. В Java 10 весь этот лес объединят в единый репозиторий, чтобы появилась возможность выполнять атомарные коммиты в репозиториях взаимозависимых наборов изменений. [304] Garbage-Collector Interface — это не интерфейс, который может быть использован разработчиками для управления сборкой мусора. Вместо этого мы получаем чистый интерфейс сборщика мусора в исходном коде JVM, позволяющий быстро и легко интегрировать альтернативные сборщики. Больше всего этому улучшению обрадуются те, кто мечтал добавить в JVM свой собственный сборщик мусора. [307] Parallel Full GC для сборщика мусора G1. В JDK 9 сборщиком мусора по умолчанию стал G1, в то время как раньше базовым сборщиком был Parallel GC, который мог собирать мусор в нескольких потоках. Теперь это сможет и G1, раньше он делал это в одном потоке, что иногда вызывало сложности. Кстати, разработчики смогут настраивать количество потоков с помощью параметра -XX:ParallelGCThreads. [310] Application Class-Data Sharing — эта наработка, принятая в версии Java 10, предлагает улучшить загрузку и отслеживание, расширить существующую функцию разделения классов (CDS), чтобы позволить классам приложений размещаться в общем архиве. Class-Data Sharing или сокращённо CDS работает с файлами расширения *class. Эта функция позволяет выбрать некое подмножество классов, обработать и сжать в специальный архив. Всё это сделано для экономии памяти. Часто разные экземпляры JVM загружают одни и те же классы, входящие в стандартную библиотеку. А CDS позволяет всем этим экземплярам JVM совместно использовать единый архив с помещёнными в него классами. Это уменьшает и время загрузки программ, и используемую память. На самом деле CDS повышает производительность запуска JVM и уменьшает объем ресурсов, когда несколько JVM работают на одной физической или виртуальной машине, начиная с пятой версии. Но раньше использование CDS ограничивалось только загрузчиком bootstrap. Теперь же расширенная версия под названием Application CDS позволяет загружать специальные архивы с классами и другим загрузчикам. [312] Thread-Local Handshakes — довольно низкоуровневое изменение внутри JVM, которое позволит выполнять обратный вызов по потокам без выполнения глобальной точки безопасности VM. Это позволит без лишних затрат останавливать отдельные потоки, а не все сразу (или ни одного). [313] Remove the Native-Header Generation Tool (javah). Ещё в Java 9 разработчики языка начали активно убирать ненужные инструменты, и JEP 313 продолжает это благое дело. Инструмент javah генерирует JNI-header’ы, если в коде есть native-методы. Полезно? Конечно, но родной компилятор javac начиная с JDK 8 сам умеет генерировать JNI-header’ы. Так что от javah теперь решили избавиться. К слову, в настоящее время ведутся разработки проекта Panama, который, в частности, может заменить JNI. [314] Additional Unicode Language-Tag Extensions данное изменение призвано улучшить класс java.util.Locale и связанные с ним API для реализации дополнительных расширений Unicode тегов языка BCP 47. В частности, теперь будут поддерживаться теги для типа валюты (cu), первого дня недели (fw), переопределения региона (rg) и часового пояса (tz). [316] Heap Allocation on Alternative Memory Devices это нововведение поможет тем, кто использует другие, отличные от DRAM, типы памяти. Поскольку технологии постоянно меняются, то использование энергонезависимой памяти с тем же интерфейсом и сходными с DRAM характеристиками производительности — объективная реальность на сегодняшний день. Так вот, JEP 316 позволяет JVM размещать кучу (heap) в других типах памяти. [317] Experimental Java-Based JIT Compiler. Недавно был анонсирован проект Metropolis, в котором предлагается переписать большую часть JVM на Java. Если вы вдруг не знали, текущая версия написана на C++. Ну а если вы уже в курсе, вероятно, в первый момент подобная идея покажется вам странной. Раз JVM написана на Java, разве вам не понадобится JVM для запуска JVM? Такая вот рекурсия, напоминающая о зеркалах напротив друг друга. Однако в реальности всё немного иначе: если JVM написана на Java, это не означает, что вы должны скомпилировать её в байт-коды. На самом деле вы можете использовать AOT-компиляцию, а затем JIT компилирует код, поскольку он работает для повышения производительности.

Для компиляции Java-кода обычно используется такой инструмент, как javac. Он преобразует программу на Java в набор класс-файлов с байт-кодами. Далее JVM запускает ваш байт-код и её интерпретатор преобразует их в инструкции процессора. Кроме интерпретатора у JVM есть и встроенный компилятор, и он тоже может создать инструкции для процессора из байт-кода. Это так называемая runtime compilation, компиляция во время запуска. Обычно такой компиляции подвергают тот код, который чаще всего использовать — это улучшает производительность.

Компилятор может выполнять действия по-разному: JIT-компиляция (just-in-time) — динамическая, прямо во время выполнения программы или AOT-компиляция (ahead-of-time) — перед выполнением.

AOT-компилятор jaotc появился в JDK 9. В настоящее время Hotspot JVM содержит два JIT-компилятора, C1 (для скорости) и C2 (для оптимизации).

JEP 317 представляет проект исследований Graal — компилятора для JDK. Это некий базис, который поможет реализовать Metropolis реальностью и дать возможность JVM соответствовать (а лучше — превзойти) по производительности текущую версию, написанную на C ++. [319] Root Certificates — набор стандартных сертификатов Certification Authority (CA) по умолчанию в JDK. Теперь в сборках OpenJDK критические компоненты безопасности, такие как TLS, будут работать по умолчанию. Это полезное дополнение, скорее всего, относится к тем действиям Oracle, которые компания предпринимает, чтобы гарантировать, что двоичные файлы OpenJDK и двоичные файлы Oracle JDK функционально одинаковы. [322] Time-Based Release Versioning — в Java 10 в Feature releases будут добавляться новые фичи, а в Update Releases — устраняться ошибки. По сути перед нами новый способ задания форматов строки версии JDK. Он устраняет довольно странную ситуацию с JDK 9. Первым обновлением значился JDK 9.0.1, что вполне логично. Второе обновление — JDK 9.0.4, что нелогично. Логика заключается в том, что в рамках схемы нумерации версий JDK 9 пространство остается между обновлениями в случае необходимости экстренного, незапланированного обновления. Поскольку обновление не было необходимым, почему бы просто не назвать его JDK 9.0.2? А вот как выглядит новый формат версий Java:
[1-9][0-9]*((\.0)*\.[1-9][0-9]*)*

Новые API

В стандартные библиотеки классов JDK 10 добавлено 73 дополнения.
  • java.awt.Toolkit

    int getMenuShortcutKeyMaskEx (): определяет, какой расширенный ключ-модификатор является соответствующим ключом ускорителя для меню ярлыков.

  • java.awt.geom.Path2D:

    void trimToSize (): Обрезает емкость этого экземпляра Path2D до его текущего размера. Приложение может использовать эту операцию для минимизации хранения пути. Этот же метод добавлен во внутренние классы Path2D.Double и Path2D.Float.

  • java.io.ByteArrayOutputStream:

    String toString (Charset): перегруженный toString, преобразует содержимое буфера в строку путем декодирования байтов с использованием указанной кодировки.

  • java.io.PrintStream и lang.io.PrintWriter:

    Оба этих класса получили три новых конструктора, которые принимают дополнительный аргумент charset.

  • java.io.Reader:

    long transferTo (Writer): считывает все символы из этого ридера и записывает символы в заданный райтер в том порядке, в котором они читаются.

  • java.lang.Runtime.Version:

    Четыре новых метода, которые возвращают целочисленное значение для новой версии (JEP 322) строковых полей: feature (), interim (), patch () и update ().

  • java.lang.StackWalker.StackFrame:

  • String getDescriptor ():

    возвращает дескриптор метода, представленного этим фреймом стека, как определено Спецификацией виртуальной машины Java.

  • String getMethodType ():

    возвращает MethodType, представляющий типы параметров, и тип возвращаемого значения для метода, представленного фреймом стека.

  • java.lang.invoke.MethodType:

    Class <?> LastParameterType (): возвращает последний тип параметра этого типа метода. Если этот тип не имеет параметров, вместо него возвращается значение sentinel void.class.

  • java.lang.management.RuntimeMXBean:

    long getPid () возвращает pid запущенной виртуальной машины Java.

  • java.lang.management.ThreadMXBean:

    ThreadInfo [] dumpAllThreads (boolean, boolean, int): возвращает информацию о потоке для всех потоков в реальном времени с трассировкой стека с указанным максимальным количеством элементов и информацией о синхронизации.

  • ThreadInfo [] getThreadInfo (long [], boolean, boolean, int):

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

  • java.lang.reflect.MalformedParameterizedTypeException:

    добавлен новый конструктор, который принимает подробное сообщение в виде строки в качестве параметра.

  • java.net.URLDecoder и java.net.URLEncoder:

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

  • java.nio.channels.Channels:

    Два новых статических перегруженных метода, newReader (ReadByteChannel, Charset) и newWriter (WriteByteChannel, Charset), которые позволяют использовать charset.

  • java.nio.file.FileStore:

    long getBlockSize (): возвращает количество байтов на блок в этом хранилище файлов.

  • java.time.chrono:

    три класса в этом пакете, HijrahEra, MiinguoEra и ThaiBuddhistEra, получили метод String getDisplayName (TextStyle, Locale). Он возвращает текстовое имя, используемое для идентификации эпохи, подходящее для представления пользователю.

  • java.time.format.DateTimeFormatter:

    localizedBy (Locale): возвращает копию этого форматтера с локализованными значениями языка, календаря, региона, десятичного стиля и / или часового пояса, которые заменяют значения в этом формате.

  • java.util:

    DoubleSummaryStatistics, IntSummaryStatistics и LongSummaryStatistics получили новый конструктор, который принимает четыре числовых значения. Он создает непустой экземпляр с указанным счетчиком, минимумом, максимумом и суммой.

  • java.util.List, java.util.Map и java.util.Set:

    каждый из этих интерфейсов обзавёлся новым статическим методом copyOf (Collection). Они возвращают неизменяемые List, Map или Set, содержащие элементы данной коллекции, в своем порядке итерации.

  • java.util.Optional, java.util.OptionalDouble, java.util.OptionalInt, java.util.OptionalLong:

    каждый из этих классов получает новый метод orElseThrow (), который по существу делает то же самое, что и get (), то есть если условие выполняется, значение возвращается. В противном случае генерируется исключение NoSuchElementException.

  • java.util.Formatter и java.util.Scanner:

    Оба этих класса получили три новых конструктора, которые на вход получают charset в дополнение к другим аргументам.

  • java.util.Properties:

    Здесь появился новый конструктор, который принимает аргумент int. Это создает пустой список свойств без значений по умолчанию и с начальным размером, содержащим указанное количество элементов без необходимости динамического изменения размера. Также появилась новая, перегруженная версия метода replace, которая принимает три параметра Object и возвращает логическое значение.

  • java.SplittableRandom:

    void nextBytes (byte []): заполняет предоставленный пользователем массив байтов с генерируемыми псевдослучайными байтами.

  • java.util.concurrent.FutureTask:

    добавлен метод toString (), который возвращает строку, идентифицирующую FutureTask, а также ее состояние завершения. Состояние (в скобках) содержит одну из строк: «Completed Normally» (нормальное завершение), «Completed Exceptionally» (завершение с исключением), «Cancelled» (отменено) или «Not completed» (не завершено).

  • java.util.concurrent.locks.StampedLock:

    новые методы boolean isLockStamp (long), boolean isOptimisticReadStamp (long), boolean isReadLockStamp (long) и boolean isWriteLockStamp (long).

  • java.jar.JarEntry:

    String getRealName (): возвращает настоящее имя этого JarEntry. Если JarEntry является записью мультирелизного jar-файла, настроенного для обработки, тогда имя, возвращаемое этим методом — имя пути версии, которую представляет JarEntry. Иначе JarEntry возвращает то же имя, что и ZipEntry.getName ().

  • java.util.jar.JarFile:

    Stream <JarEntry> versionedStream (): возвращает поток записей в файле с версией jar. Подобно методу getRealName для JarEntry, связан с мультирелизными jar-файлами.

  • java.util.spi.LocaleNameProvider:

    getDisplayUnicodeExtensionKey (String, Locale): возвращает локализованное имя для данного Unicode extension key. getDisplayUnicodeExtensionType (String, String, Locale): возвращает локализованное имя для данного Unicode extension key.

  • java.util.stream.Collectors:

    toUnmodifiableList (), toUnmodifiableSet (), toUnmodifiableMap (Function, Function), toUnmodifiableMap (Function, Function, BinaryOperator) — эти четыре новых метода возвращают коллекторы (Collectors), которые накапливают входные элементы в соответствующую немодифицируемую коллекцию.

  • java.lang.model.SourceVersion:

    теперь это поле RELEASE_10 для представления версии JDK 10.

  • java.lang.model.util.TypeKindVisitor6 и javax.lang.model.util.TypeKindVisitor9:

    что-то не вполне понятное:).

  • R visitNoTypeAsModule (NoType, P):

    посещает псевдо-тип MODULE.

  • javax.remote.management.rmi.RMIConnectorServer:

    У этого класса было добавлено два поля: CREDENTIALS_FILTER_PATTERN и SERIAL_FILTER_PATTERN.

  • javax.ButtonModel:

    Представляете, Swing все еще обновляется!

  • ButtonGroup getGroup ():

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

  • javax.plaf.basic.BasicMenuUI:

    Dimension getMinimumSize (JComponent): возвращает минимальный размер указанного компонента, подходящий для внешнего вида.

Что еще почитать?

Чем порадует новая версия JDK

К чему приведёт частый выпуск новых версий JDK