Java 17 является выпуском с долгосрочной поддержкой (LTS), который стал общедоступным 14 сентября 2021 года, загрузите Java 17 здесь .
Java 17 содержит 14 элементов JEP.
- 1. JEP 306: Восстановить Всегда Строгую Семантику С Плавающей Запятой
- 2. JEP 356: Усовершенствованные генераторы Псевдослучайных чисел
- 3. JEP 382: Новый конвейер рендеринга mac OS
- 4. JEP 391: Порт macOS/AArch64
- 5. JEP 398: Не рекомендуется использовать API апплета для удаления
- 6. JEP 403: Строго инкапсулировать JDKInternals
- 7. JEP 406: Сопоставление шаблонов для переключателя (предварительный просмотр)
- 7.1 если… другая цепочка
- 7.2 Сопоставление с образцом и нулевое значение
- 7.3 Уточнение шаблонов в коммутаторе
- 8. JEP 407: Удалить активацию RMI
- 9. JEP 409: Закрытые Классы
- 10. JEP 410: Удалите экспериментальный компилятор AOT и JIT
- 11. JEP 411: Откажитесь от Менеджера безопасности для удаления
- 12. JEP 412: API внешних функций и памяти (Инкубатор)
- 13. JEP 414: Векторный API (Второй инкубатор)
- 14. JEP 415: Фильтры десериализации, Зависящие от контекста
- Скачать Исходный Код
- Рекомендации
Функции разработчика Java 17. генератор псевдослучайных чисел, сопоставление шаблонов для коммутатора (предварительный просмотр), закрытый класс (стандартная функция), API внешней функции и памяти (инкубатор), фильтры динамической десериализации.
1. JEP 306: Восстановить Всегда Строгую Семантику С Плавающей Запятой
Этот ДЖИП предназначен для программ, чувствительных к числовым данным, в основном для научных целей; Он снова сделал операции с плавающей запятой по умолчанию строгими или Strictfp
, гарантируя одинаковые результаты вычислений с плавающей запятой на каждой платформе.
Краткая история
- До Java 1.2 все вычисления с плавающей запятой были строгими; и это приводило к перегреву оборудования на базе x87.
- Начиная с Java 1.2, нам нужно ключевое слово
strictfp
, чтобы включить строгий расчет с плавающей запятой. Расчет с плавающей запятой по умолчанию был изменен со строгого на слегка отличающиеся вычисления с плавающей запятой (избегайте проблем с перегревом). - Теперь, поскольку Intel и AMD поддерживают оба SSE2 (потоковые расширения SIMD 2) расширения, которые могли бы поддерживать строгие операции с плавающей запятой JVM без перегревов, таким образом, предыдущие (до Java 1.2) проблемы с перегревом на оборудовании на базе x87 являются непочтительными в современном оборудовании.
- Java 17 восстанавливает строгие вычисления с плавающей запятой до Java 1.2 по умолчанию, что означает, что ключевое слово
strictfp
теперь необязательно.
Дальнейшее Чтение
2. JEP 356: Усовершенствованные генераторы Псевдослучайных чисел
Этот ДЖИП представил новый интерфейс под названием Генератор случайных чисел
, чтобы упростить реализацию или использование будущих генераторов псевдослучайных чисел (PRNG) алгоритмов.
package java.util.random; public interface RandomGenerator { //... }
В приведенном ниже примере используется новая Java 17 randomgeneratorfactory
, чтобы получить знаменитые Xoshiro256PlusPlus
Алгоритмы PRNG для генерации случайных целых чисел в определенном диапазоне от 0 до 10.
package com.mkyong.java17.jep356; import java.util.random.RandomGenerator; import java.util.random.RandomGeneratorFactory; public class JEP356 { public static void main(String[] args) { // legacy // RandomGeneratorFactory.of("Random").create(42); // default L32X64MixRandom // RandomGenerator randomGenerator = RandomGeneratorFactory.getDefault().create(); // Passing the same seed to random, and then calling it will give you the same set of numbers // for example, seed = 999 RandomGenerator randomGenerator = RandomGeneratorFactory.of("Xoshiro256PlusPlus").create(999); System.out.println(randomGenerator.getClass()); int counter = 0; while(counter<=10){ // 0-10 int result = randomGenerator.nextInt(11); System.out.println(result); counter++; } } }
Выход
class jdk.random.Xoshiro256PlusPlus 4 6 9 5 7 6 5 0 6 10 4
Приведенный ниже код генерирует все алгоритмы Java 17 PRNG.
RandomGeneratorFactory.all() .map(fac -> fac.group()+ " : " +fac.name()) .sorted() .forEach(System.out::println);
Выход
LXM : L128X1024MixRandom LXM : L128X128MixRandom LXM : L128X256MixRandom LXM : L32X64MixRandom LXM : L64X1024MixRandom LXM : L64X128MixRandom LXM : L64X128StarStarRandom LXM : L64X256MixRandom Legacy : Random Legacy : SecureRandom Legacy : SplittableRandom Xoroshiro : Xoroshiro128PlusPlus Xoshiro : Xoshiro256PlusPlus
Java 17 также переработала устаревшие случайные классы, такие как java.util. Случайный
, Расщепляемый случай
и SecureRandom
для расширения нового RandomGenerator
интерфейса.
Дальнейшее Чтение
- JEP 356: Усовершенствованные генераторы Псевдослучайных чисел
- Улучшенные генераторы Псевдослучайных Чисел Java 17
3. JEP 382: Новый конвейер рендеринга mac OS
Apple отказалась от библиотеки рендеринга OpenGL в выпуске mac OS 10.14 (сентябрь 2018) в пользу нового Металлического каркаса для повышения производительности.
Этот JEEP изменяет внутренний конвейер рендеринга Java 2D (например, графический интерфейс Swing) для macOS с API Apple OpenGL на API Apple Metal; это внутреннее изменение; новых API Java 2D нет, и никакие существующие API не изменяются.
Дальнейшее Чтение
4. JEP 391: Порт macOS/AArch64
У Apple есть долгосрочный план по переводу своего Mac с x64 на AArch64 (например, процессоры Apple M1).
Этот JEP-порт JDK для запуска на платформах AArch64 в mac OS.
Дальнейшее Чтение
5. JEP 398: Не рекомендуется использовать API апплета для удаления
API Java-апплета не имеет значения, потому что большинство веб-браузеров удалили поддержку плагинов Java-браузера.
Java 9 устарел API апплета.
@Deprecated(since = "9") public class Applet extends Panel { //... }
Этот JEP пометил API апплета для удаления.
@Deprecated(since = "9", forRemoval = true) @SuppressWarnings("removal") public class Applet extends Panel { //... }
Дальнейшее Чтение
6. JEP 403: Строго инкапсулировать JDKInternals
Многие сторонние библиотеки, платформы и инструменты получают доступ к внутренним API и пакетам JDK. Java 16, JEP 396 по умолчанию обеспечивает надежную инкапсуляцию (нам не разрешен легкий доступ к внутренним API). Тем не менее, мы все еще можем использовать --незаконный доступ
для переключения на простую инкапсуляцию, чтобы по-прежнему получать доступ к внутренним API.
Этот JEP является преемником вышеупомянутого Java 16 JEP 396, и он делает еще один шаг, удаляя параметр --незаконный доступ
, что означает, что у нас нет способов доступа к внутренним API, за исключением критических внутренних API, таких как sun.misc. Небезопасно
.
Попробуйте --незаконный доступ =предупредить
в Java 17.
java --illegal-access=warn OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=warn; support was removed in 17.0
Дальнейшее Чтение
7. JEP 406: Сопоставление шаблонов для переключателя (предварительный просмотр)
Этот JEP добавляет сопоставление шаблонов для переключателей
операторов и выражений. Поскольку это функция предварительного просмотра, нам нужно использовать опцию --enable-предварительный просмотр
, чтобы включить ее.
7.1 если… другая цепочка
До Java 17, как правило, мы использовали цепочку тестов if...else
для нескольких возможностей.
package com.mkyong.java17.jep406; public class JEP406 { public static void main(String[] args) { System.out.println(formatter("Java 17")); System.out.println(formatter(17)); } static String formatter(Object o) { String formatted = "unknown"; if (o instanceof Integer i) { formatted = String.format("int %d", i); } else if (o instanceof Long l) { formatted = String.format("long %d", l); } else if (o instanceof Double d) { formatted = String.format("double %f", d); } else if (o instanceof String s) { formatted = String.format("String %s", s); } return formatted; } }
В Java 17 мы можем переписать приведенный выше код следующим образом:
package com.mkyong.java17.jep406; public class JEP406 { public static void main(String[] args) { System.out.println(formatterJava17("Java 17")); System.out.println(formatterJava17(17)); } static String formatterJava17(Object o) { return switch (o) { case Integer i -> String.format("int %d", i); case Long l -> String.format("long %d", l); case Double d -> String.format("double %f", d); case String s -> String.format("String %s", s); default -> o.toString(); }; } }
7.2 Сопоставление с образцом и нулевое значение
Теперь мы можем проверить null
вход переключатель
напрямую.
Старый кодекс.
package com.mkyong.java17.jep406; public class JEP406 { public static void main(String[] args) { testString("Java 16"); // Ok testString("Java 11"); // LTS testString(""); // Ok testString(null); // Unknown! } static void testString(String s) { if (s == null) { System.out.println("Unknown!"); return; } switch (s) { case "Java 11", "Java 17" -> System.out.println("LTS"); default -> System.out.println("Ok"); } } }
Новый код.
package com.mkyong.java17.jep406; public class JEP406 { public static void main(String[] args) { testStringJava17("Java 16"); // Ok testStringJava17("Java 11"); // LTS testStringJava17(""); // Ok testStringJava17(null); // Unknown! } static void testStringJava17(String s) { switch (s) { case null -> System.out.println("Unknown!"); case "Java 11", "Java 17" -> System.out.println("LTS"); default -> System.out.println("Ok"); } } }
7.3 Уточнение шаблонов в коммутаторе
Просмотрите приведенный ниже фрагмент кода. Чтобы проверить Треугольник t
и т.вычислить площадь()
, нам нужно создать дополнительное если
условие.
class Shape {} class Rectangle extends Shape {} class Triangle extends Shape { int calculateArea(){ //... } } static void testTriangle(Shape s) { switch (s) { case null: break; case Triangle t: if (t.calculateArea() > 100) { System.out.println("Large triangle"); break; }else{ System.out.println("Triangle"); } default: System.out.println("Unknown!"); } }
Java 17 допускает так называемые предопределенные шаблоны или защищенные шаблоны
, как показано ниже:
static void testTriangle2(Shape s) { switch (s) { case null -> {} case Triangle t && (t.calculateArea() > 100) -> System.out.println("Large triangle"); case Triangle t -> System.out.println("Triangle"); default -> System.out.println("Unknown!"); } }
Дальнейшее Чтение
Для получения дополнительных примеров и объяснений, пожалуйста, посетите этот JEP 406: Сопоставление шаблонов для переключателя (предварительный просмотр)
8. JEP 407: Удалить активацию RMI
Java 15, JEP385 устарела Активация RMI для удаления.
Этот ДЖИП удалил активацию RMI или java.rmi.activation
пакет.
Дальнейшее Чтение
9. JEP 409: Закрытые Классы
Java 15, JEEP 360 и Java 16, JPG 397 представлен [запечатанный класс(https://cr.openjdk.java.net/~briangoetz/amber/datum.html) в качестве функции предварительного просмотра.
Этот JEP завершил запечатанные классы в качестве стандартной функции в Java 17 без изменений по сравнению с Java 16.
Запечатанные классы и интерфейсы управляют или ограничивают, кто может быть подтипом.
public sealed interface Command permits LoginCommand, LogoutCommand, PluginCommand{ //... }
Дальнейшее Чтение
10. JEP 410: Удалите экспериментальный компилятор AOT и JIT
Java 9, JPG 295 представила компиляцию с опережением времени (инструмент jaotc
) в качестве экспериментальной функции. Позже Java 10, JEP 317 предложил его снова в качестве экспериментального JIT-компилятора.
Однако эта функция мало используется с тех пор, как они были введены, и для ее поддержки потребовались значительные усилия, поэтому этот JEP удалил экспериментальную версию на основе Java досрочно (AOT) и как раз вовремя (JIT) компилятор
Удаляются следующие пакеты, классы, инструменты и коды AOT:
jdk.аот
— инструмент jatcjdk.внутренний.vm.компилятор
— компилятор Graaljdk.внутренний.vm.компилятор.управление
— Мбеан Грааляsrc/точка доступа/общий доступ/aot
— сбрасывает и загружает Код AOT- Дополнительный код, охраняемый
# если INCLUDE_AOT
Дальнейшее Чтение
11. JEP 411: Откажитесь от Менеджера безопасности для удаления
Java 1.0 представила Менеджер безопасности для защиты Java-кода на стороне клиента, и теперь это не имеет значения.
Этот JEP осуждает Менеджера безопасности для удаления.
package java.lang; * @since 1.0 * @deprecated The Security Manager is deprecated and subject to removal in a * future release. There is no replacement for the Security Manager. * See JEP 411 for * discussion and alternatives. */ @Deprecated(since="17", forRemoval=true) public class SecurityManager { //... }
Дальнейшее Чтение
12. JEP 412: API внешних функций и памяти (Инкубатор)
Этот API внешних функций и памяти позволяет разработчику получить доступ к коду за пределами JVM (внешние функции), данным, хранящимся за пределами JVM (данные вне кучи), и получить доступ к памяти, не управляемой JVM (внешняя память).
P.S Это инкубационная функция; нужно добавить — добавить модули jdk.инкубатор.иностранный для компиляции и запуска кода Java.
История
- Java 14 JEP 370 представил API доступа к внешней памяти (Инкубатор).
- Java 15 JEP 383 представил API доступа к внешней памяти (Второй инкубатор).
- Java 16 JEP 389 представил API внешнего компоновщика (Инкубатор).
- Java 16 JEP 393 представил API доступа к внешней памяти (Третий инкубатор).
- Java 17 JEP 412 представил API внешних функций и памяти (Инкубатор).
Пожалуйста, обратитесь к предыдущим примерам API внешнего компоновщика в Java 16.
Дальнейшее Чтение
13. JEP 414: Векторный API (Второй инкубатор)
Java 16, JEP 414 представил новый векторный API в качестве инкубационного API .
Этот JEP улучшает производительность векторного API и другие улучшения, такие как поддержка операций с символами, перевод байтовых векторов в логические массивы и из них и т.д.
Дальнейшее Чтение
- JEP 414: Векторный API (Второй инкубатор)
- Википедия – Автоматическая векторизация
- Автоматическая векторизация в Java
14. JEP 415: Фильтры десериализации, Зависящие от контекста
В Java десериализация ненадежных данных опасна, прочитайте OWASP – Десериализация ненадежных данных и Брайан Гетц – К лучшей сериализации .
В Java 9, JEP 290 введена фильтрация сериализации для предотвращения уязвимостей десериализации.
14.1 В приведенном ниже примере создается пользовательский фильтр с использованием шаблона.
package com.mkyong.java17.jep415; import java.io.Serializable; public class DdosExample implements Serializable { @Override public String toString() { return "running ddos...!"; } }
package com.mkyong.java17.jep415; import java.io.*; public class JEP290 { public static void main(String[] args) throws IOException { byte[] bytes = convertObjectToStream(new DdosExample()); InputStream is = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(is); // Setting a Custom Filter Using a Pattern // need full package path // the maximum number of bytes in the input stream = 1024 // allows classes in com.mkyong.java17.jep415.* // allows classes in the java.base module // rejects all other classes !* ObjectInputFilter filter1 = ObjectInputFilter.Config.createFilter( "maxbytes=1024;com.mkyong.java17.jep415.*;java.base/*;!*"); ois.setObjectInputFilter(filter1); try { Object obj = ois.readObject(); System.out.println("Read obj: " + obj); } catch (ClassNotFoundException e) { e.printStackTrace(); } } private static byte[] convertObjectToStream(Object obj) { ByteArrayOutputStream boas = new ByteArrayOutputStream(); try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { ois.writeObject(obj); return boas.toByteArray(); } catch (IOException ioe) { ioe.printStackTrace(); } throw new RuntimeException(); } }
Выход
Read obj: running ddos...!
Приведенный ниже пример отклонит все классы в пакете com.mkyong.java 17.jep415. *
:
byte[] bytes = convertObjectToStream(new DdosExample()); ObjectInputFilter filter1 = ObjectInputFilter.Config.createFilter( "!com.mkyong.java17.jep415.*;java.base/*;!*");
Повторите его; на этот раз мы не сможем десериализовать объект.
Exception in thread "main" java.io.InvalidClassException: filter status: REJECTED at java.base/java.io.ObjectInputStream.filterCheck(ObjectInputStream.java:1412)
14.2 В приведенном ниже примере создается фильтр десериализации для отклонения всех классов, которые расширили JКомпонент
.
package com.mkyong.java17.jep415; import javax.swing.*; import java.io.Serializable; public class JComponentExample extends JComponent implements Serializable { }
package com.mkyong.java17.jep415; import javax.swing.*; import java.io.*; public class JEP290_B { public static void main(String[] args) throws IOException { byte[] bytes = convertObjectToStream(new JComponentExample()); InputStream is = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(is); ois.setObjectInputFilter(createObjectFilter()); try { Object obj = ois.readObject(); System.out.println("Read obj: " + obj); } catch (ClassNotFoundException e) { e.printStackTrace(); } } // reject all JComponent classes private static ObjectInputFilter createObjectFilter() { return filterInfo -> { Class> clazz = filterInfo.serialClass(); if (clazz != null) { return (JComponent.class.isAssignableFrom(clazz)) ? ObjectInputFilter.Status.REJECTED : ObjectInputFilter.Status.ALLOWED; } return ObjectInputFilter.Status.UNDECIDED; }; } private static byte[] convertObjectToStream(Object obj) { ByteArrayOutputStream boas = new ByteArrayOutputStream(); try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { ois.writeObject(obj); return boas.toByteArray(); } catch (IOException ioe) { ioe.printStackTrace(); } throw new RuntimeException(); } }
Выход
Exception in thread "main" java.io.InvalidClassException: filter status: REJECTED at java.base/java.io.ObjectInputStream.filterCheck(ObjectInputStream.java:1412) at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:2053) at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1907) at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2209) at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1742) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:514) at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:472) at com.mkyong.java17.jep415.JEP290_B.main(JEP290_B.java:17)
14.3 Добавлена Java 17 разрешить фильтр
полоса Фильтр отклонения
для Фильтра ввода объекта
интерфейс для более быстрого создания фильтров десериализации.
allowFilter(Predicate>, ObjectInputFilter.Status) rejectFilter(Predicate >, ObjectInputFilter.Status)
Для приведенного выше примера в 14.2 теперь мы можем выполнить рефакторинг кода, как показано ниже:
// Java 9 private static ObjectInputFilter createObjectFilter() { return filterInfo -> { Class> clazz = filterInfo.serialClass(); if (clazz != null) { return (JComponent.class.isAssignableFrom(clazz)) ? ObjectInputFilter.Status.REJECTED : ObjectInputFilter.Status.ALLOWED; } return ObjectInputFilter.Status.UNDECIDED; }; } // Java 17 // reject all JComponent classes ObjectInputFilter jComponentFilter = ObjectInputFilter.rejectFilter( JComponent.class::isAssignableFrom, ObjectInputFilter.Status.UNDECIDED); ois.setObjectInputFilter(jComponentFilter);
14.4 Возвращаясь к Java 17, в этом JEP 415 была введена концепция фабрики фильтров, двоичного оператора , для выбора различных фильтров десериализации динамически или в зависимости от контекста. Завод определяет, как объединить два фильтра или заменить фильтр.
Ниже приведен пример фабрики фильтров Java 17 для объединения двух фильтров десериализации.
package com.mkyong.java17.jep415; import java.io.*; import java.util.function.BinaryOperator; public class JEP415_B { static class PrintFilterFactory implements BinaryOperator{ @Override public ObjectInputFilter apply( ObjectInputFilter currentFilter, ObjectInputFilter nextFilter) { System.out.println("Current filter: " + currentFilter); System.out.println("Requested filter: " + nextFilter); // Returns a filter that merges the status of a filter and another filter return ObjectInputFilter.merge(nextFilter, currentFilter); // some logic and return other filters // reject all JComponent classes /*return filterInfo -> { Class> clazz = filterInfo.serialClass(); if (clazz != null) { if(JComponent.class.isAssignableFrom(clazz)){ return ObjectInputFilter.Status.REJECTED; } } return ObjectInputFilter.Status.ALLOWED; };*/ } } public static void main(String[] args) throws IOException { // Set a filter factory PrintFilterFactory filterFactory = new PrintFilterFactory(); ObjectInputFilter.Config.setSerialFilterFactory(filterFactory); // create a maxdepth and package filter ObjectInputFilter filter1 = ObjectInputFilter.Config.createFilter( "com.mkyong.java17.jep415.*;java.base/*;!*"); ObjectInputFilter.Config.setSerialFilter(filter1); // Create a filter to allow String.class only ObjectInputFilter intFilter = ObjectInputFilter.allowFilter( cl -> cl.equals(String.class), ObjectInputFilter.Status.REJECTED); // if pass anything other than String.class, hits filter status: REJECTED //byte[] byteStream =convertObjectToStream(99); // Create input stream byte[] byteStream =convertObjectToStream("hello"); InputStream is = new ByteArrayInputStream(byteStream); ObjectInputStream ois = new ObjectInputStream(is); ois.setObjectInputFilter(intFilter); try { Object obj = ois.readObject(); System.out.println("Read obj: " + obj); } catch (ClassNotFoundException e) { e.printStackTrace(); } } private static byte[] convertObjectToStream(Object obj) { ByteArrayOutputStream boas = new ByteArrayOutputStream(); try (ObjectOutputStream ois = new ObjectOutputStream(boas)) { ois.writeObject(obj); return boas.toByteArray(); } catch (IOException ioe) { ioe.printStackTrace(); } throw new RuntimeException(); } }
Выход
Current filter: null Requested filter: com.mkyong.java17.jep415.*;java.base/*;!* Current filter: com.mkyong.java17.jep415.*;java.base/*;!* Requested filter: predicate( com.mkyong.java17.jep415.JEP415_B$$Lambda$22/0x0000000800c01460@15aeb7ab, ifTrue: ALLOWED, ifFalse:REJECTED) Read obj: hello
Дальнейшее Чтение
Пожалуйста, прочтите ссылки ниже для получения дополнительных примеров фильтров десериализации:
- JEP 415: Фильтры десериализации, Зависящие от контекста
- JEEP 290: Фильтрация Входящих Данных Сериализации
- Фильтрация сериализации
Скачать Исходный Код
$клон git $клон git
$cd java-17
Рекомендации
- Проект OpenJDK 17
- Исходный код OpenJDK
- Википедия – SSE2 (Потоковые расширения SIMD 2)
- Википедия – строгий закон
- Википедия – Генератор псевдослучайных чисел (PRNG)
- Улучшенные генераторы Псевдослучайных Чисел Java 17
- Металлический Каркас Apple
- Википедия – Apple M1
- Классы данных и запечатанные типы для Java
- Более простая сериализация с записями
- Сериализация записей
- Автоматическая векторизация в Java
- Векторный процессор
- Скалярный процессор
- На Пути к Лучшей Сериализации
- Сопоставление шаблонов для Java
- История версий Java
- Фильтрация сериализации
- OWASP – Десериализация ненадежных данных
- Брайан Гетц – К Лучшей Сериализации
- Примеры сериализации и десериализации Java
Оригинал: “https://mkyong.com/java/what-is-new-in-java-17/”