«1. Обзор

В сентябре 2019 года был выпущен JDK 13 в соответствии с новым шестимесячным графиком выпуска Java. В этой статье мы рассмотрим новые функции и улучшения, представленные в этой версии.

2. Функции предварительного просмотра для разработчиков

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

Нам нужно указать —enable-preview в качестве флага командной строки, чтобы использовать функции предварительного просмотра. Давайте рассмотрим их подробно.

2.1. Выражения переключателя (JEP 354)

Сначала мы видели выражения переключателя в JDK 12. Выражения переключателя Java 13 основываются на предыдущей версии, добавляя новый оператор yield.

Используя yield, теперь мы можем эффективно возвращать значения из выражения переключателя:

@Test
@SuppressWarnings("preview")
public void whenSwitchingOnOperationSquareMe_thenWillReturnSquare() {
    var me = 4;
    var operation = "squareMe";
    var result = switch (operation) {
        case "doubleMe" -> {
            yield me * 2;
        }
        case "squareMe" -> {
            yield me * me;
        }
        default -> me;
    };

    assertEquals(16, result);
}

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

2.2. Текстовые блоки (JEP 355)

Вторая функция предварительного просмотра — это текстовые блоки для многострочных строк, таких как встроенные JSON, XML, HTML и т. д.

Раньше, чтобы встроить JSON в наш код, мы объявляли его как Строковый литерал:

String JSON_STRING 
  = "{\r\n" + "\"name\" : \"Baeldung\",\r\n" + "\"website\" : \"https://www.%s.com/\"\r\n" + "}";

Теперь давайте напишем тот же JSON, используя текстовые блоки String:

String TEXT_BLOCK_JSON = """
{
    "name" : "Baeldung",
    "website" : "https://www.%s.com/"
}
""";

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

Кроме того, доступны все функции String:

@Test
public void whenTextBlocks_thenStringOperationsWorkSame() {        
    assertThat(TEXT_BLOCK_JSON.contains("Baeldung")).isTrue();
    assertThat(TEXT_BLOCK_JSON.indexOf("www")).isGreaterThan(0);
    assertThat(TEXT_BLOCK_JSON.length()).isGreaterThan(0);
}

Кроме того, java.lang.String теперь имеет три новых метода для управления текстовыми блоками:

    stripIndent() — имитирует компилятор для удаления случайных белых space translateEscapes() — переводит управляющие последовательности, такие как «\\\\t», в «\\t» formatted() — работает так же, как String::format, но для текстовых блоков

Возьмем быстрый взгляд на пример String::formatted:

assertThat(TEXT_BLOCK_JSON.formatted("baeldung").contains("www.baeldung.com")).isTrue();
assertThat(String.format(JSON_STRING,"baeldung").contains("www.baeldung.com")).isTrue();

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

3. Динамические архивы CDS (JEP 350)

Совместное использование данных классов (CDS) уже некоторое время является заметной функцией Java HotSpot VM. Это позволяет совместно использовать метаданные класса между различными JVM, чтобы сократить время запуска и объем памяти. JDK 10 расширил эту возможность, добавив приложения CDS (AppCDS), чтобы дать разработчикам возможность включать классы приложений в общий архив. JDK 12 дополнительно расширил эту функцию, чтобы по умолчанию включить архивы CDS.

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

Благодаря динамическому архивированию JDK 13 упростил этот процесс. Теперь мы можем создать общий архив во время выхода из приложения. Это устранило необходимость в пробных запусках.

Чтобы приложения могли создавать динамический общий архив поверх системного архива по умолчанию, нам нужно добавить параметр -XX:ArchiveClassesAtExit и указать имя архива в качестве аргумента:

java -XX:ArchiveClassesAtExit=<archive filename> -cp <app jar> AppName

Затем мы можем использовать новый создал архив для запуска того же приложения с параметром -XX:SharedArchiveFile:

java -XX:SharedArchiveFile=<archive filename> -cp <app jar> AppName

4. ZGC: Uncommit Unused Memory (JEP 351)

Сборщик мусора Z был представлен в Java 11 как сборщик мусора с малой задержкой. механизм, так что время паузы GC никогда не превышало 10 мс. Однако, в отличие от других GC HotSpot VM, таких как G1 и Shenandoah, он не был оборудован для возврата неиспользуемой памяти кучи в операционную систему. Java 13 добавила эту возможность в ZGC.

Теперь мы получаем уменьшенный объем памяти наряду с улучшением производительности.

Начиная с Java 13, ZGC по умолчанию возвращает операционной системе незафиксированную память до тех пор, пока не будет достигнут указанный минимальный размер кучи. Если мы не хотим использовать эту функцию, мы можем вернуться к Java 11 следующим образом:

    «Использование параметра -XX:-ZUncommit или Установка равных минимального (-Xms) и максимального (-Xmx) размеров кучи

Кроме того, ZGC теперь имеет максимальный поддерживаемый размер кучи 16 ТБ. Ранее пределом было 4 ТБ.

5. Повторная реализация устаревшего API сокетов (JEP 353)

Мы видели API сокетов (java.net.Socket и java.net.ServerSocket) как неотъемлемую часть Java с момента ее появления. Однако за последние двадцать лет они ни разу не модернизировались. Написанные на устаревших Java и C, они были громоздкими и сложными в обслуживании.

Java 13 изменила эту тенденцию и заменила базовую реализацию, чтобы привести API в соответствие с футуристическими потоками пользовательского режима. Вместо PlainSocketImpl интерфейс провайдера теперь указывает на NioSocketImpl. Эта недавно написанная реализация основана на той же внутренней инфраструктуре, что и java.nio.

Опять же, у нас есть способ вернуться к использованию PlainSocketImpl. Мы можем запустить JVM с системным свойством -Djdk.net.usePlainSocketImpl, установленным как true, чтобы использовать более старую реализацию. По умолчанию используется NioSocketImpl.

6. Прочие изменения

Помимо перечисленных выше JEP, в Java 13 есть еще несколько заметных изменений:

    java.nio — метод FileSystems.newFileSystem(Path, Map\u003cString, ?\u003e ) добавлен java.time — добавлено новое официальное название японской эпохи javax.crypto — поддержка MS Cryptography Next Generation (CNG) javax.security — добавлено свойство jdk.sasl.disabledMechanisms для отключения механизмов SASL javax.xml. crypto — введены новые строковые константы для представления URI Canonical XML 1.1. javax.xml.parsers — добавлены новые методы для создания экземпляров фабрик DOM и SAX с поддержкой пространств имен. Поддержка Unicode обновлена ​​до версии 12.1. рефералы области

Кроме того, предлагается удалить несколько API. К ним относятся три метода String, перечисленные выше, и API javax.security.cert.

Среди удалений есть инструмент rmic и старые функции инструмента JavaDoc. Реализации SocketImpl до JDK 1.4 также больше не поддерживаются.

7. Заключение

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

Как обычно, исходный код доступен на GitHub.