JavaRush /Blog Jawa /Random-JV /Из 8 в 13: полный обзор версий Java. Часть 2

Из 8 в 13: полный обзор версий Java. Часть 2

Diterbitake ing grup
Эта статья является второй частью моего обзора по нововведениям в Java версий 8-13. Первая часть — здесь. Без лишних предисловий двигаемся дальше: в 25 сентября 2018, когда и вышла новая JDK:

Java 11

Из 8 в 13: полный обзор версий Java. Часть 2 - 1

var (в лямбде)

Отныне и во веки веков мы можем указать типы лямбда-параметров or пропустить их при написании лямбда-выражения (неявно типизированных лямбда-выражений):

Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
Также можно добавлять аннотации к лямбда-параметрам без необходимости писать полное Name типа переменной:

Function<String, String> append = (@NonNull var string) -> string + " Text";

Z (ZGC)

ZGC — это новый сборщик мусора, который не работает. Он выделяет новую память, но никогда не перезапускает ее. ZGC обещает управлять большими объемами памяти с высокой пропускной способностью и коротким временем паузы (ZGC доступен только на 64-битных платформах). Эталонная окраска — ZGC использует 64-битные указатели с техникой, называемой окрашиванием указателей. Цветные указатели хранят дополнительную информацию об an objectх в куче. Когда память становится фрагментированной, это помогает избежать снижения производительности, когда GC необходимо найти место для нового распределения. Сборка мусора с помощью ZGC состоит из таких этапов:
  1. остановки мира: мы ищем отправные точки для достижения an objectов в куче (например, локальных переменных or статических полей);
  2. пересечение граф an objectов, начиная с корневых ссылок. Мы отмечаем каждый an object, который достигаем (ZGC ходит по графу an objectов и исследует цветные указатели, отмечая доступные an objectы);
  3. обработки некоторых крайних случаев, например, слабых ссылок;
  4. перемещение живых an objectов, освобождая большие участки кучи, чтобы ускорить распределение.
  5. когда начинается фаза перемещения, ZGC разделяет кучу на pages и работает по одной странице за раз;
  6. ZGC заканчивает движение любых корней, и происходит остальная часть перемещения.
Данная тема весьма сложная и запутанная. Подробное рассмотрение тянет на отдельную статью, поэтому просто оставлю это здесь:

Epsilon GC

Эпсилон — это сборщик мусора, который обрабатывает выделение памяти, но не реализует Howой-либо реальный механизм ее восстановления памяти. Как только доступная куча Java будет исчерпана, JVM закроется. То есть, если в бесконечном массиве запустить создание an object без привязки к ссылке с данным сборщиком мусора, приложение упадёт с OutOfMemoryError (а если с любым другим нет, так How он будет подчищать an objectы без ссылок). Зачем он нужен? А вот зачем:
  1. Тестирование производительности.
  2. Тестирование давления памяти.
  3. Тестирование интерфейса VM.
  4. Чрезвычайно недолгая работа.
  5. Улучшения латентности последней капли.
  6. Улучшения пропускной способности последней капли.
Полезные ссылки: Другие нововведения:
  1. ByteArrayOutputStream получил метод void writeBytes(byte []), записывающий все byteы из аргумента в OutputStream.
  2. FileReader и FileWriter получor новые конструкторы, позволяющие указывать Charset.
  3. Path отхватил два новых метода, of(String, String []) возвращает Path из строкового аргумента пути or последовательности строк, которые при объединении образуют строку пути и of(URI): возвращает Path из URI.
  4. Pattern — получил метод asMatchPredicate(), который проверяет, соответствует ли заданная строка ввода, заданному шаблону (позволяет ли создать предикат по регулярному выражению, чтобы можно было, например, фильтровать данные в stream).
  5. String отхватил много полезных методов, таких How:
    • String strip(): вернёт нам строку, которая является этой строкой, при этом удаляются все пробелы в начале и в конце строки (аналог trim(), но по-другому определяет пробелы);
    • String stripLeading(): вернёт нам строку, которая является этой строкой, при этом удаляются все пробелы в начале строки;
    • String stripTrailing(): вернёт нам строку, которая является этой строкой, при этом удаляются все пробелы в конце строки;
    • Stream lines(): вернёт нам Stream из String, извлеченных из этой строки, поделенных разделителями строк;
    • String repeat(int): вернёт нам строку, которая представляет собой конкатенацию этой строки, повторяющееся количество раз.
    • boolean isBlank(): вернёт нам true, если строка пуста or содержит только пробелы, иначе false.
  6. Thread — были удалены методы destroy() и stop(Throwable).
  7. Files получил ряд новых методов:
    • String readString(Path): читает все данные из file в строку, при этом деcodeируя из byte в символы с использованием codeировки UTF-8;
    • String readString(Path, Charset): так же, How и в методе выше, с разницей в том, что деcodeирование из byte в символы происходит с использованием указанной Charset;
    • Path writeString (Path, CharSequence, OpenOption []): записывает последовательность символов в файл. Символы codeируются в byteы, используя codeировку UTF-8;
    • Path writeString(Path, CharSequence,Charset, OpenOption []): такой же метод, что и выше, только символы codeируются в byteы, используя codeировку, указанную в Charset.
Это были самые интересные нововведения API (по моему скромному мнению), вот пара материалов для более детального ознакомления:

Java 12

Проходит полгода, и мы видим следующую ступень эволюции Java. Значит, пора доставать лопатку знаний и копать. Из 8 в 13: полный обзор версий Java. Часть 2 - 2

Update G1

Для G1 были внесены такие улучшения:
  1. Возврат неиспользуемой выделенной памяти

    В Java heap memory есть такое понятие How неиспользуемая память (or по-другому — неактивная). В Java 12 решor пофиксить эту проблему, теперь:

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

    Данное улучшение фокусируется на быстродействии за счет автоматического возврата памяти из кучи в ОС, когда G1 не используется.

  2. Прерывание смешанных коллекций, когда время паузы превышено

    G1 использует механизм анализа для выбора объема работы, необходимого для сбора мусора. Он собирает живые an objectы без остановки после определения набора и запуска очистки. Это приводит к тому, что сборщик мусора превышает целевое meaning времени паузы. Собственно, такую проблему и решает улучшение, так How если время выполнения следующего шага выходит за рамки разумного, этот шаг можно прервать.

Microbenchmark

В Java 12 ввели тесты микробенчмаркинга, чтобы производительность JVM легко тестировалась с помощью уже существующих тестов. Это было бы очень полезно для всех, кто хочет работать над самой JVM. Добавляемые тесты создаются с использованием Java Microbenchmark Harness (JMH). Эти тесты позволяют проводить непрерывное тестирование производительности на JVM. JEP 230 предлагает ввести около 100 тестов, причем новые тесты вводятся по мере выпуска новых версий Java. Вот пример добавляемых тестов.

Shenandoah

Это алгоритм сборки мусора (GC), цель которого — гарантировать низкое время отклика (нижний предел — 10-500 мс). Это уменьшает время паузы GC при выполнении работы по очищению одновременно с работающими потоками Java. В Shenandoah время паузы не зависит от размера кучи. Это означает, что время паузы будет одинаковым независимо от размера вашей кучи. Это экспериментальная функция, которая не включена в стандартную (Oracle) сборку OpenJDK.

Improve Switch

В Java 12 улучшены выражения Switch для сопоставления с образцом. Был введен, новый синтаксис L →. Вот список ключевых моментов нового switch:
  1. Новый синтаксис устраняет необходимость в операторе break для предотвращения ошибок.
  2. Выражения переключателя больше не проваливаются.
  3. Кроме того, мы можем определить несколько констант в одной метке.
  4. default регистр теперь обязателен в выражениях переключателей.
  5. break используется в выражениях Switch для возврата значений из самого регистра (по сути switch может возвращать значения).
Рассмотрим How пример:

var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
            break "Please insert a valid day.";
      else
            break "Looks like a Sunday.";
  }
};
Definitive Guide To Switch Expressions In Java 13 Другие нововведения:
  1. String:

    transform(Function f) — применяет предоставленную функцию к строке. Результат может не быть строкой.
    indent(int x) — добавляет x пробелов в строку. Если параметр отрицателен, то это количество начальных пробелов будет удалено(если это возможно).

  2. Files — отхватил такой метод How mismatch(), который, в свою очередь, находит и возвращает позицию первого несовпадающего byteа в содержимом двух файлов or -1L, если нет несоответствия.

  3. Появился новый класс — CompactNumberFormat, для форматирования десятичного числа в компактной форме. Пример такой компактной формы — 1M instead of 1000000. Таким образом, требуется всего лишь два два instead of девяти символов.

  4. Существует также новый enum, NumberFormatStyle, у которого есть два значения — LONG и SHORT.

  5. InputStream получил метод — skipNBytes(long n): пропустить n-ое количество byteов из входного потока.

Интересные ссылки по Java 12:

Java 13

Мир не стоит на месте, шевелится, развивается, How и Java — Java 13. Из 8 в 13: полный обзор версий Java. Часть 2 - 3

Text block

Java всегда немного страдала от определения строк. Если нам нужно определить строку с пробелом, перенос строки, кавычку or ещё что-то, это вызывало некоторые трудности, так приходилось использовать специальные символы: например, \n для переноса строки, or экранировать некоторые из самой строки. Это существенно снижает читаемость codeа, и занимает лишнее время при написании такой строки. Эта становится особо заметным при написании строк, отображающих JSON, XML, HTML и т.д. В итоге если мы хотим написать небольшой Json, это будет выглядеть How-то так:

String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
И тут на сцену выходит Java 13 и предлагает нам свое решение в виде тройных двойных кавычек до и после текста (которые и обозвали текстовыми блоками). Давайте рассмотрим предыдущий пример json с использованием данного нововведения:

String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
В разы проще и наглядней, не правда ли? Также было в String было добавлено три новых метода, соответственно, для управления данными блоками:
  • stripIndent(): удаляет случайные пробелы из строки. Это полезно, если вы читаете многострочные строки и хотите применить такое же исключение случайных пробелов, How это происходит с явным объявлением (по сути имитирует компилятор для удаления случайных пробелов);
  • formatted(Object... args ): аналог format(String format, Object... arg), но для текстовых блоков;
  • translateEscapes(): возвращает строку с escape-последовательностями (например, \ r), переведенными в соответствующее meaning Unicode.

Improve Switch

Выражения-переключатели были введены в Java 12, а 13 уточняет их. В 12 вы определяете возвращаемые значения с помощью break. В 13 возвращаемое meaning заменor на yield. Теперь выражение со switch, которое было у нас в разделе Java 12, можно переписать How:

var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
          yield "Please insert a valid day.";
      else
          yield "Looks like a Sunday.";
  }
};
Хотя нам программистам, уже знакомым с Java, было нормально принять break, но, тем не менее, это было довольно странно. What break true пытается мне сказать? Новое (условно новое) ключевое слово yield более понятно, и в будущем оно может появиться в других местах, где возвращаются значения. Кому глубоко интересна данная тема, рекомендую ознакомиться с данными материалами:

Dynamic CDS Archives

CDS — Class-Data Sharing. Позволяет упаковывать набор часто используемых классов в архив, который позже может быть загружен несколькими экземплярами JVM. Зачем нам это? Дело в том, что в процессе загрузки классов JVM делает довольно много ресурсозатратных действий, таких How чтение классов, сохранение их во внутренних структурах, проверка правильности прочитанных классов, поиск и загрузка зависимых классов и т. д., и лишь после всего этого классы готовы к работе. Понятное дело, попусту тратится большое количество ресурсов, ведь экземпляры JVM часто могут загружать одни и те же классы. Например String, LinckedList, Integer. Ну or же классы одного и того же applications, а все это — ресурсы. Если бы мы выполнor все необходимые действия лишь один раз и после поместor переработанные классы в архив, который может быть подгружен в память нескольких JVM, это могло бы существенно сэкономить место в памяти и сократить время запуска applications. Собственно, CDS дает возможность создать именно такой архив. Java 9 позволяла добавлять в архив только системные классы. Java 10 — включать в архив классы applications. Creation такого архива состоит из:
  • создания списка классов, загружаемых приложением;
  • создания так необходимого нам архива с найденными классами.
Нововведение в Java 13 улучшает CDS так, чтобы он мог создавать архив по завершении applications. Это означает, что два шага, приведенные выше, теперь будут объединены в один. И ещё один важный момент: только классы, которые были загружены во время работы applications, будут добавлены в архив. Другими словами словами, те классы, которые все же содержатся в application.jar, но по Howим-то причинам на были загружены, не добавятся в архив.

Update Socket API

API Socket (java.net.Socket и java.net.ServerSocket) — по сути неотъемлемая часть Java с момента ее появления, но при этом сокеты ни разу не апдейтor за последний двадцаток лет. Написанные на C и Java, они были очень и очень громоздкими и сложными в обслуживании. Но Java 13 решила внести свои коррективы в это всё дело и заменила базовую реализацию. Теперь instead of PlainSocketImpl интерфейс провайдера заменяется на NioSocketImpl. Эта новая codeированная реализация основана на той же внутренней инфраструктуре, что и java.nio. По сути класс использует механизм буферного кэша и блокировки java.util.concurrent (которые являются сегментными), а не синхронизированные методы. Он больше не требует нативного codeа, тем самым упрощая портирование на разные платформы. Всё же, у нас есть способ вернуться к использованию PlainSocketImpl, но отныне по дефолту используется NioSocketImpl.

Memory Return for ZGC

Как мы помним, Z сборщик мусора ввели в Java 11 How механизм сборки мусора с малой задержкой, чтобы GC пауза никогда не превышала 10 мс. Но при этом, в отличие от остальных виртуальных GC HotSpot, таких How Shenandoah и G1, он мог возвращать неиспользованную динамическую память в ОС. Данная модификация добавляет эту возможность J в ZGC. Соответственно, мы получаем уменьшенный объем памяти вместе с улучшением производительности, и ZGC теперь возвращает не зафиксированную память операционной системе по умолчанию, пока не будет достигнут указанный минимальный размер кучи. И ещё: у ZGC теперь есть максимальный поддерживаемый размер кучи 16 ТБ. Раньше 4ТБ было пределом. Другие нововведения:
  1. javax.security — добавлено свойство jdk.sasl.disabledMechanisms для отключения механизмов SASL.
  2. java.nio — добавлен метод FileSystems.newFileSystem (Path, Map <String,?>) — соответственно, для создания нового file.
  3. Классы java.nio теперь имеют абсолютные (в отличие от относительных) get и set-методы. Они, How и базовый абстрактный класс Buffer, включают метод slice() для извлечения части буфера.
  4. В javax.xml.parsers добавлены методы для создания экземпляров фабрик DOM и SAX (с поддержкой пространств имен).
  5. Поддержка Unicode обновлена ​​до версии 12.1.
Интересные ссылки по Java 13:

Итоги

Мы могли бы и пройтись по заявленным нововведениям в Java 14, но так How она довольно-таки скоро увидит свет — выпуск JDK 14 запланирован на 17 марта 2020 года, лучше всего будет провести отдельный, полноценный обзор на неё уже непосредственно после выхода. Еще хотелось бы обратить внимание на то, что в других языках программирования с большими перерывами между выпусками, How например в Python 2–3, нет совместимости: то есть если code написан на Python 2, нужно будет изрядно попотеть, переводя его на 3. Java — особенная в этом отношении, поскольку она чрезвычайно обратно совместима. Это означает, что ваша программа на Java 5 or 8 гарантированно будет работать с виртуальной machine Java 8-13 — с некоторыми исключениями, о которых вам сейчас не нужно беспокоиться. Понятное дело, что это не работает наоборот: например, если ваше приложение юзает функции Java 13, которые просто недоступны в Java 8 JVM. На этом у меня сегодня всё, тем кто дочитал до этого места — респект)) Из 8 в 13: полный обзор версий Java. Часть 2 - 5
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION