Java21的新特性

news2024/9/28 23:32:11

Java语言特性系列

  • Java5的新特性
  • Java6的新特性
  • Java7的新特性
  • Java8的新特性
  • Java9的新特性
  • Java10的新特性
  • Java11的新特性
  • Java12的新特性
  • Java13的新特性
  • Java14的新特性
  • Java15的新特性
  • Java16的新特性
  • Java17的新特性
  • Java18的新特性
  • Java19的新特性
  • Java20的新特性
  • Java21的新特性
  • Java22的新特性

本文主要讲述一下Java21的新特性

版本号

java -version
openjdk version "21" 2023-09-19
OpenJDK Runtime Environment (build 21+35-2513)
OpenJDK 64-Bit Server VM (build 21+35-2513, mixed mode, sharing)

从version信息可以看出是build 21+35

特性列表

JEP 430: String Templates (Preview)

在java21之前,字符串拼接或者字符串与表达式组合主要是用StringBuilder、String::format、java.text.MessageFormat,不过可读性都不是太好,java21引入了StringTemplate(java.lang.StringTemplate)来解决这个问题。

@PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
public interface StringTemplate {
	List<String> fragments();
	List<Object> values();
	default String interpolate() {
        return StringTemplate.interpolate(fragments(), values());
    }
    default <R, E extends Throwable> R
    process(Processor<? extends R, ? extends E> processor) throws E {
        Objects.requireNonNull(processor, "processor should not be null");

        return processor.process(this);
    }

    static String interpolate(List<String> fragments, List<?> values) {
        Objects.requireNonNull(fragments, "fragments must not be null");
        Objects.requireNonNull(values, "values must not be null");
        int fragmentsSize = fragments.size();
        int valuesSize = values.size();
        if (fragmentsSize != valuesSize + 1) {
            throw new IllegalArgumentException("fragments must have one more element than values");
        }
        JavaTemplateAccess JTA = SharedSecrets.getJavaTemplateAccess();
        return JTA.interpolate(fragments, values);
    }

    Processor<String, RuntimeException> STR = StringTemplate::interpolate;
    Processor<StringTemplate, RuntimeException> RAW = st -> st;

    @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
    @FunctionalInterface
    public interface Processor<R, E extends Throwable> {
    	R process(StringTemplate stringTemplate) throws E;
    	static <T> Processor<T, RuntimeException> of(Function<? super StringTemplate, ? extends T> process) {
            return process::apply;
        }

        @PreviewFeature(feature=PreviewFeature.Feature.STRING_TEMPLATES)
        public sealed interface Linkage permits FormatProcessor {
        	MethodHandle linkage(List<String> fragments, MethodType type);
        }
    }
}

StringTemplate是个接口,它定义了fragments、values、interpolate、process方法,同时提供了interpolate、process方法的默认实现;同时内置了两个processor,分别是STR和RAW,他们的区别在于RAW可以获取到StringTemplate类型,STR则是StringTemplate执行了interpolate方法之后的结果,获得到的是最终结果String;其基本语法就是用\{}来包含变量或者表达式

RAW示例

    @Test
    public void testRaw() {
        int x = 10;
        int y = 20;
        StringTemplate st = RAW."\{x} + \{y} = \{x + y}";
        List<String> fragments = st.fragments();
        List<Object> values = st.values();
        log.info("fragments:{}, values:{}, st:{}", fragments, values, st.interpolate());
    }

输出fragments:[, + , = , ], values:[10, 20, 30], st:10 + 20 = 30

STR示例

    @Test
    public void testStr() {
        String name = "Joan";
        String info = STR."My name is \{name}";
        System.out.println(info);
    }

输出My name is Joan

也支持方法调用和表达式

    @Test
    public void testStrExpression() {
        String filePath = "tmp.dat";
        File file = new File(filePath);
        String msg = STR. "The file \{ filePath } \{ file.exists() ? "does" : "does not" } exist" ;
        System.out.println(msg);
    }

最后输出The file tmp.dat does not exist

对于还有格式化需求的,提供了java.util.FMT

	@Test
    public void testFmt() {
        record Rectangle(String name, double width, double height) {
            double area() {
                return width * height;
            }
        }
        Rectangle[] zone = new Rectangle[] {
                new Rectangle("Alfa", 17.8, 31.4),
                new Rectangle("Bravo", 9.6, 12.4),
                new Rectangle("Charlie", 7.1, 11.23),
        };
        String table = FMT."""
    Description     Width    Height     Area
    %-12s\{zone[0].name}  %7.2f\{zone[0].width}  %7.2f\{zone[0].height}     %7.2f\{zone[0].area()}
    %-12s\{zone[1].name}  %7.2f\{zone[1].width}  %7.2f\{zone[1].height}     %7.2f\{zone[1].area()}
    %-12s\{zone[2].name}  %7.2f\{zone[2].width}  %7.2f\{zone[2].height}     %7.2f\{zone[2].area()}
    \{" ".repeat(28)} Total %7.2f\{zone[0].area() + zone[1].area() + zone[2].area()}
    """;
        System.out.println(table);
    }

也可以自定义processor

@Test
    public void testCustomProcessor() {
        var MYJSON = StringTemplate.Processor.of(
                (StringTemplate st) -> com.alibaba.fastjson.JSON.parseObject(st.interpolate())
        );

        String name    = "Joan Smith";
        String phone   = "555-123-4567";
        String address = "1 Maple Drive, Anytown";
        JSONObject doc = MYJSON."""
    {
        "name":    "\{name}",
        "phone":   "\{phone}",
        "address": "\{address}"
    }
    """;
        System.out.println(doc);
    }

JEP 431: Sequenced Collections

java21引入了java.util.SequencedCollection、java.util.SequencedMap来统一各类集合的顺序方法方法

public interface SequencedCollection<E> extends Collection<E> {
	SequencedCollection<E> reversed();
	default void addFirst(E e) {
        throw new UnsupportedOperationException();
    }
    default void addLast(E e) {
        throw new UnsupportedOperationException();
    }
    default E getFirst() {
        return this.iterator().next();
    }
    default E getLast() {
        return this.reversed().iterator().next();
    }
    default E removeFirst() {
        var it = this.iterator();
        E e = it.next();
        it.remove();
        return e;
    }
    default E removeLast() {
        var it = this.reversed().iterator();
        E e = it.next();
        it.remove();
        return e;
    }
}

SequencedCollection继承了Collection接口,同时定义了reversed,提供了addFirst、addLast、getFirst、getLast、removeFirst、removeLast的default实现;List、SequencedSet接口都继承了SequencedCollection接口

public interface SequencedMap<K, V> extends Map<K, V> {
	SequencedMap<K, V> reversed();
	default Map.Entry<K,V> firstEntry() {
        var it = entrySet().iterator();
        return it.hasNext() ? new NullableKeyValueHolder<>(it.next()) : null;
    }
    default Map.Entry<K,V> lastEntry() {
        var it = reversed().entrySet().iterator();
        return it.hasNext() ? new NullableKeyValueHolder<>(it.next()) : null;
    }
    default Map.Entry<K,V> pollFirstEntry() {
        var it = entrySet().iterator();
        if (it.hasNext()) {
            var entry = new NullableKeyValueHolder<>(it.next());
            it.remove();
            return entry;
        } else {
            return null;
        }
    }
    default Map.Entry<K,V> pollLastEntry() {
        var it = reversed().entrySet().iterator();
        if (it.hasNext()) {
            var entry = new NullableKeyValueHolder<>(it.next());
            it.remove();
            return entry;
        } else {
            return null;
        }
    }
    default V putFirst(K k, V v) {
        throw new UnsupportedOperationException();
    }
    default V putLast(K k, V v) {
        throw new UnsupportedOperationException();
    }
    default SequencedSet<K> sequencedKeySet() {
        class SeqKeySet extends AbstractMap.ViewCollection<K> implements SequencedSet<K> {
            Collection<K> view() {
                return SequencedMap.this.keySet();
            }
            public SequencedSet<K> reversed() {
                return SequencedMap.this.reversed().sequencedKeySet();
            }
            public boolean equals(Object other) {
                return view().equals(other);
            }
            public int hashCode() {
                return view().hashCode();
            }
        }
        return new SeqKeySet();
    }
    default SequencedCollection<V> sequencedValues() {
        class SeqValues extends AbstractMap.ViewCollection<V> implements SequencedCollection<V> {
            Collection<V> view() {
                return SequencedMap.this.values();
            }
            public SequencedCollection<V> reversed() {
                return SequencedMap.this.reversed().sequencedValues();
            }
        }
        return new SeqValues();
    }
    default SequencedSet<Map.Entry<K, V>> sequencedEntrySet() {
        class SeqEntrySet extends AbstractMap.ViewCollection<Map.Entry<K, V>>
                implements SequencedSet<Map.Entry<K, V>> {
            Collection<Map.Entry<K, V>> view() {
                return SequencedMap.this.entrySet();
            }
            public SequencedSet<Map.Entry<K, V>> reversed() {
                return SequencedMap.this.reversed().sequencedEntrySet();
            }
            public boolean equals(Object other) {
                return view().equals(other);
            }
            public int hashCode() {
                return view().hashCode();
            }
        }
        return new SeqEntrySet();
    }              
}

SequencedMap接口继承了Map接口,它定义了reversed方法,同时提供了firstEntry、lastEntry、pollFirstEntry、pollLastEntry、putFirst、putLast、sequencedKeySet、sequencedValues、sequencedEntrySet方法的默认实现

此次版本的变动:
SequencedCollection

  • List现在有作为其直接的超级接口,SequencedCollection
  • Deque现在有作为其直接的超级接口,SequencedCollection
  • LinkedHashSet另外实现SequencedSet接口
  • SortedSet现在有作为其直接的超级接口,SequencedSet
  • LinkedHashMap另外实现SequencedMap接口
  • SortedMap现在有作为它的直接超级接口,SequencedMap

另外Collections还提供了工厂方法用于返回不可变类型

Collections.unmodifiableSequencedCollection(sequencedCollection)
Collections.unmodifiableSequencedSet(sequencedSet)
Collections.unmodifiableSequencedMap(sequencedMap)

JEP 439: Generational ZGC

ZGC分代回收无疑是一个重磅的GC特性,ZGC之前的版本不支持分代回收,此次支持分代回收的话,可以更方便地对年轻代进行收集,提高GC性能。目前是分代与非分代都支持,使用分代则通过-XX:+UseZGC-XX:+ZGenerational开启,后续版本将会把分代设置为默认的,而-XX:-ZGenerational用于开启非分代,最后将会废除非分代的支持,届时ZGenerational参数也就没有作用了。

JEP 440: Record Patterns

JDK19的JEP 405: Record Patterns (Preview)将Record的模式匹配作为第一次preview
JDK20的JEP 432: Record Patterns (Second Preview)作为第二次preview
此次在JDK21则作为正式版本发布,使用示例如下

record Point(int x, int y) {}

// As of Java 21
static void printSum(Object obj) {
    if (obj instanceof Point(int x, int y)) {
        System.out.println(x+y);
    }
}

enum Color { RED, GREEN, BLUE }
record ColoredPoint(Point p, Color c) {}
record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}
// As of Java 21
static void printUpperLeftColoredPoint(Rectangle r) {
    if (r instanceof Rectangle(ColoredPoint ul, ColoredPoint lr)) {
         System.out.println(ul.c());
    }
}

static void printColorOfUpperLeftPoint(Rectangle r) {
    if (r instanceof Rectangle(ColoredPoint(Point p, Color c),
                               ColoredPoint lr)) {
        System.out.println(c);
    }
}

JEP 441: Pattern Matching for switch

在JDK14JEP 305: Pattern Matching for instanceof (Preview)作为preview
在JDK15JEP 375: Pattern Matching for instanceof (Second Preview)作为第二轮的preview
在JDK16JEP 394: Pattern Matching for instanceof转正
JDK17引入JEP 406: Pattern Matching for switch (Preview)
JDK18的JEP 420: Pattern Matching for switch (Second Preview)则作为第二轮preview
JDK19的JEP 427: Pattern Matching for switch (Third Preview)作为第三轮preview
JDK20的JEP 433: Pattern Matching for switch (Fourth Preview)作为第四轮preview
而此次JDK21将Pattern Matching for switch作为正式版本发布,示例如下

// Prior to Java 21
static String formatter(Object obj) {
    String formatted = "unknown";
    if (obj instanceof Integer i) {
        formatted = String.format("int %d", i);
    } else if (obj instanceof Long l) {
        formatted = String.format("long %d", l);
    } else if (obj instanceof Double d) {
        formatted = String.format("double %f", d);
    } else if (obj instanceof String s) {
        formatted = String.format("String %s", s);
    }
    return formatted;
}

// As of Java 21
static String formatterPatternSwitch(Object obj) {
    return switch (obj) {
        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        -> obj.toString();
    };
}

// As of Java 21
static void testFooBarNew(String s) {
    switch (s) {
        case null         -> System.out.println("Oops");
        case "Foo", "Bar" -> System.out.println("Great");
        default           -> System.out.println("Ok");
    }
}

// As of Java 21
static void testStringEnhanced(String response) {
    switch (response) {
        case null -> { }
        case "y", "Y" -> {
            System.out.println("You got it");
        }
        case "n", "N" -> {
            System.out.println("Shame");
        }
        case String s
        when s.equalsIgnoreCase("YES") -> {
            System.out.println("You got it");
        }
        case String s
        when s.equalsIgnoreCase("NO") -> {
            System.out.println("Shame");
        }
        case String s -> {
            System.out.println("Sorry?");
        }
    }
}

// As of Java 21
static void exhaustiveSwitchWithBetterEnumSupport(CardClassification c) {
    switch (c) {
        case Suit.CLUBS -> {
            System.out.println("It's clubs");
        }
        case Suit.DIAMONDS -> {
            System.out.println("It's diamonds");
        }
        case Suit.HEARTS -> {
            System.out.println("It's hearts");
        }
        case Suit.SPADES -> {
            System.out.println("It's spades");
        }
        case Tarot t -> {
            System.out.println("It's a tarot");
        }
    }
}

// As of Java 21
sealed interface Currency permits Coin {}
enum Coin implements Currency { HEADS, TAILS } 

static void goodEnumSwitch1(Currency c) {
    switch (c) {
        case Coin.HEADS -> {    // Qualified name of enum constant as a label
            System.out.println("Heads");
        }
        case Coin.TAILS -> {
            System.out.println("Tails");
        }
    }
}

static void goodEnumSwitch2(Coin c) {
    switch (c) {
        case HEADS -> {
            System.out.println("Heads");
        }
        case Coin.TAILS -> {    // Unnecessary qualification but allowed
            System.out.println("Tails");
        }
    }
}

// As of Java 21
static void testNew(Object obj) {
    switch (obj) {
        case String s when s.length() == 1 -> ...
        case String s                      -> ...
        ...
    }
}

JEP 442: Foreign Function & Memory API (Third Preview)

Foreign Function & Memory (FFM) API包含了两个incubating API
JDK14的JEP 370: Foreign-Memory Access API (Incubator)引入了Foreign-Memory Access API作为incubator
JDK15的JEP 383: Foreign-Memory Access API (Second Incubator)Foreign-Memory Access API作为第二轮incubator
JDK16的JEP 393: Foreign-Memory Access API (Third Incubator)作为第三轮,它引入了Foreign Linker API (JEP 389)
FFM API在JDK 17的JEP 412: Foreign Function & Memory API (Incubator)作为incubator引入
FFM API在JDK 18的JEP 419: Foreign Function & Memory API (Second Incubator)作为第二轮incubator
JDK19的JEP 424: Foreign Function & Memory API (Preview)则将FFM API作为preview API
JDK20的JEP 434: Foreign Function & Memory API (Second Preview)作为第二轮preview
JDK21则作为第三轮的preview,使用示例

.javac --release 21 --enable-preview ...java --enable-preview ...

// 1. Find foreign function on the C library path
Linker linker          = Linker.nativeLinker();
SymbolLookup stdlib    = linker.defaultLookup();
MethodHandle radixsort = linker.downcallHandle(stdlib.find("radixsort"), ...);
// 2. Allocate on-heap memory to store four strings
String[] javaStrings = { "mouse", "cat", "dog", "car" };
// 3. Use try-with-resources to manage the lifetime of off-heap memory
try (Arena offHeap = Arena.ofConfined()) {
    // 4. Allocate a region of off-heap memory to store four pointers
    MemorySegment pointers
        = offHeap.allocateArray(ValueLayout.ADDRESS, javaStrings.length);
    // 5. Copy the strings from on-heap to off-heap
    for (int i = 0; i < javaStrings.length; i++) {
        MemorySegment cString = offHeap.allocateUtf8String(javaStrings[i]);
        pointers.setAtIndex(ValueLayout.ADDRESS, i, cString);
    }
    // 6. Sort the off-heap data by calling the foreign function
    radixsort.invoke(pointers, javaStrings.length, MemorySegment.NULL, '\0');
    // 7. Copy the (reordered) strings from off-heap to on-heap
    for (int i = 0; i < javaStrings.length; i++) {
        MemorySegment cString = pointers.getAtIndex(ValueLayout.ADDRESS, i);
        javaStrings[i] = cString.getUtf8String(0);
    }
} // 8. All off-heap memory is deallocated here
assert Arrays.equals(javaStrings,
                     new String[] {"car", "cat", "dog", "mouse"});  // true

JEP 443: Unnamed Patterns and Variables (Preview)

Unnamed Patterns and Variables支持用_来替代没有使用的变量声明,比如

r instanceof Point _
r instanceof ColoredPoint(Point(int x, int _), Color _)
if (r instanceof ColoredPoint(_, Color c)) { ... c ... }
switch (b) {
    case Box(RedBall _), Box(BlueBall _) -> processBox(b);
    case Box(GreenBall _)                -> stopProcessing();
    case Box(_)                          -> pickAnotherBox();
}
int acc = 0;
for (Order _ : orders) {
    if (acc < LIMIT) { 
        ... acc++ ...
    }
}
while (q.size() >= 3) {
    var x = q.remove();
    var _ = q.remove();
    var _ = q.remove(); 
    ... new Point(x, 0) ...
}

JEP 444: Virtual Threads

在JDK19[https://openjdk.org/jeps/425](JEP 425: Virtual Threads (Preview))作为第一次preview
在JDK20JEP 436: Virtual Threads (Second Preview)作为第二次preview,此版本java.lang.ThreadGroup被永久废弃
在JDK21版本,Virtual Threads正式发布,与之前版本相比,这次支持了threadlocal,然后也可以通过Thread.Builder来创建,而且也支持threaddump(jcmd <pid> Thread.dump_to_file -format=json <file>)

使用示例

void handle(Request request, Response response) {
    var url1 = ...
    var url2 = ...
 
    try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
        var future1 = executor.submit(() -> fetchURL(url1));
        var future2 = executor.submit(() -> fetchURL(url2));
        response.send(future1.get() + future2.get());
    } catch (ExecutionException | InterruptedException e) {
        response.fail(e);
    }
}
 
String fetchURL(URL url) throws IOException {
    try (var in = url.openStream()) {
        return new String(in.readAllBytes(), StandardCharsets.UTF_8);
    }
}

一般用Executors.newVirtualThreadPerTaskExecutor()是想通过池化技术来减少对象创建开销,不过由于虚拟线程相比平台线程更为"廉价",因而不再需要池化,如果需要控制虚拟线程数则可以使用信号量的方式,因而提供了Thread.Builder来直接创建虚拟线程,示例如下:

Thread thread = Thread.ofVirtual().name("duke").unstarted(runnable);
Thread.startVirtualThread(Runnable) 

JEP 445: Unnamed Classes and Instance Main Methods (Preview)

未命名的类和实例main方法这个特性可以简化hello world示例,方便java新手入门,示例如下

        static void main(String[] args) {
            System.out.println("static main with args");
        }

        static void main() {
            System.out.println("static main without args");
        }

        void main(String[] args) {
            System.out.println("main with args");
        }

        void main() {
            System.out.println("main with without args");
        }

javac --release 21 --enable-preview Main.javajava --enable-preview Main
其中main方法选择的优先顺序是static的优于非static的,然后有args的优于没有args的

JEP 446: Scoped Values (Preview)

Scoped Values在JDK20的JEP 429: Scoped Values (Incubator)作为Incubator
此次在JDK21作为preview版本
ScopedValue是一种类似ThreadLocal的线程内/父子线程传递变量的更优方案。ThreadLocal提供了一种无需在方法参数上传递通用变量的方法,InheritableThreadLocal使得子线程可以拷贝继承父线程的变量。但是ThreadLocal提供了set方法,变量是可变的,另外remove方法很容易被忽略,导致在线程池场景下很容易造成内存泄露。ScopedValue则提供了一种不可变、不拷贝的方案,即不提供set方法,子线程不需要拷贝就可以访问父线程的变量。具体使用如下:

class Server {
  public final static ScopedValue<User> LOGGED_IN_USER = ScopedValue.newInstance();
 
  private void serve(Request request) {
    // ...
    User loggedInUser = authenticateUser(request);
    ScopedValue.where(LOGGED_IN_USER, loggedInUser)
               .run(() -> restAdapter.processRequest(request));
    // ...
  }
}

通过ScopedValue.where可以绑定ScopedValue的值,然后在run方法里可以使用,方法执行完毕自行释放,可以被垃圾收集器回收

JEP 448: Vector API (Sixth Incubator)

JDK16引入了JEP 338: Vector API (Incubator)提供了jdk.incubator.vector来用于矢量计算
JDK17进行改进并作为第二轮的incubatorJEP 414: Vector API (Second Incubator)
JDK18的JEP 417: Vector API (Third Incubator)进行改进并作为第三轮的incubator
JDK19的JEP 426:Vector API (Fourth Incubator)作为第四轮的incubator
JDK20的JEP 438: Vector API (Fifth Incubator)作为第五轮的incubator
而JDK21则作为第六轮的incubator,使用示例如下

static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;

void vectorComputation(float[] a, float[] b, float[] c) {
    int i = 0;
    int upperBound = SPECIES.loopBound(a.length);
    for (; i < upperBound; i += SPECIES.length()) {
        // FloatVector va, vb, vc;
        var va = FloatVector.fromArray(SPECIES, a, i);
        var vb = FloatVector.fromArray(SPECIES, b, i);
        var vc = va.mul(va)
                   .add(vb.mul(vb))
                   .neg();
        vc.intoArray(c, i);
    }
    for (; i < a.length; i++) {
        c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
    }
}

JEP 449: Deprecate the Windows 32-bit x86 Port for Removal

废弃了对Windows 32-bit x86 (x86-32)的移植,以便后续版本删除

JEP 451: Prepare to Disallow the Dynamic Loading of Agents

对将代理动态加载到正在运行的 JVM 中时发出警告,后续版本将不允许动态加载agent。

在 JDK 9 及更高版本中,可以通过-XX:-EnableDynamicAgentLoading禁止动态加载agent。
在 JDK 21 中,允许动态加载agent,但 JVM 会在发生时发出警告。例如:

WARNING: A {Java,JVM TI} agent has been loaded dynamically (file:/u/bob/agent.jar)
WARNING: If a serviceability tool is in use, please run with -XX:+EnableDynamicAgentLoading to hide this warning
WARNING: If a serviceability tool is not in use, please run with -Djdk.instrument.traceUsage for more information
WARNING: Dynamic loading of agents will be disallowed by default in a future release

若要允许工具动态加载agent而不发出警告,用户必须在命令行上使用-XX:+EnableDynamicAgentLoading

JEP 452: Key Encapsulation Mechanism API

Key Encapsulation Mechanism(KEM)是一种现代加密技术,它使用非对称或公钥加密来保护对称密钥。传统的方法是使用公钥加密一个随机生成的对称密钥,但这需要填充,并且可能难以证明安全。相反,KEM利用公钥的属性派生一个相关的对称密钥,这不需要填充。

此次新增了javax.crypto.KEM、javax.crypto.KEMSpi

package javax.crypto;

public class DecapsulateException extends GeneralSecurityException;

public final class KEM {

    public static KEM getInstance(String alg)
        throws NoSuchAlgorithmException;
    public static KEM getInstance(String alg, Provider p)
        throws NoSuchAlgorithmException;
    public static KEM getInstance(String alg, String p)
        throws NoSuchAlgorithmException, NoSuchProviderException;

    public static final class Encapsulated {
        public Encapsulated(SecretKey key, byte[] encapsulation, byte[] params);
        public SecretKey key();
        public byte[] encapsulation();
        public byte[] params();
    }

    public static final class Encapsulator {
        String providerName();
        int secretSize();           // Size of the shared secret
        int encapsulationSize();    // Size of the key encapsulation message
        Encapsulated encapsulate();
        Encapsulated encapsulate(int from, int to, String algorithm);
    }

    public Encapsulator newEncapsulator(PublicKey pk)
            throws InvalidKeyException;
    public Encapsulator newEncapsulator(PublicKey pk, SecureRandom sr)
            throws InvalidKeyException;
    public Encapsulator newEncapsulator(PublicKey pk, AlgorithmParameterSpec spec,
                                        SecureRandom sr)
            throws InvalidAlgorithmParameterException, InvalidKeyException;

    public static final class Decapsulator {
        String providerName();
        int secretSize();           // Size of the shared secret
        int encapsulationSize();    // Size of the key encapsulation message
        SecretKey decapsulate(byte[] encapsulation) throws DecapsulateException;
        SecretKey decapsulate(byte[] encapsulation, int from, int to,
                              String algorithm)
                throws DecapsulateException;
    }

    public Decapsulator newDecapsulator(PrivateKey sk)
            throws InvalidKeyException;
    public Decapsulator newDecapsulator(PrivateKey sk, AlgorithmParameterSpec spec)
            throws InvalidAlgorithmParameterException, InvalidKeyException;

}

它主要是提供了newEncapsulator、newDecapsulator方法,使用示例如下

// Receiver side
KeyPairGenerator g = KeyPairGenerator.getInstance("ABC");
KeyPair kp = g.generateKeyPair();
publishKey(kp.getPublic());

// Sender side
KEM kemS = KEM.getInstance("ABC-KEM");
PublicKey pkR = retrieveKey();
ABCKEMParameterSpec specS = new ABCKEMParameterSpec(...);
KEM.Encapsulator e = kemS.newEncapsulator(pkR, specS, null);
KEM.Encapsulated enc = e.encapsulate();
SecretKey secS = enc.key();
sendBytes(enc.encapsulation());
sendBytes(enc.params());

// Receiver side
byte[] em = receiveBytes();
byte[] params = receiveBytes();
KEM kemR = KEM.getInstance("ABC-KEM");
AlgorithmParameters algParams = AlgorithmParameters.getInstance("ABC-KEM");
algParams.init(params);
ABCKEMParameterSpec specR = algParams.getParameterSpec(ABCKEMParameterSpec.class);
KEM.Decapsulator d = kemR.newDecapsulator(kp.getPrivate(), specR);
SecretKey secR = d.decapsulate(em);

// secS and secR will be identical

JEP 453: Structured Concurrency (Preview)

在JDK19的JEP 428: Structured Concurrency (Incubator)作为第一次incubator
在JDK20的JEP 437: Structured Concurrency (Second Incubator)作为第二次incubator
此次在JDK21则作为preview,使用示例如下

Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        Supplier<String>  user  = scope.fork(() -> findUser());
        Supplier<Integer> order = scope.fork(() -> fetchOrder());

        scope.join()            // Join both subtasks
             .throwIfFailed();  // ... and propagate errors

        // Here, both subtasks have succeeded, so compose their results
        return new Response(user.get(), order.get());
    }
}

细项解读

上面列出的是大方面的特性,除此之外还有一些api的更新及废弃,主要见JDK 21 Release Notes,这里举几个例子。

添加项

  • Math.clamp() and StrictMath.clamp() Methods (JDK-8301226)
  • New String indexOf(int,int,int) and indexOf(String,int,int) Methods to Support a Range of Indices (JDK-8302590)
  • New splitWithDelimiters() Methods Added to String and java.util.regex.Pattern (JDK-8305486)
  • System.exit() and Runtime.exit() Logging (JDK-8301627)
  • The java.net.http.HttpClient Is Now AutoCloseable (JDK-8267140)
  • New StringBuilder and StringBuffer repeat Methods (JDK-8302323)
  • Last Resort G1 Full GC Moves Humongous Objects (JDK-8191565)

移除项

  • Removed SECOM Trust System’s RootCA1 Root Certificate (JDK-8295894)
  • java.io.File’s Canonical Path Cache Is Removed (JDK-8300977)
  • Removal of the java.compiler System Property (JDK-8041676)
  • The java.lang.Compiler Class Has Been Removed (JDK-8205129)
  • Remove the JAR Index Feature (JDK-8302819)
  • Removal of G1 Hot Card Cache (JDK-8225409)
  • Obsolete Legacy HotSpot Parallel Class Loading Workaround Option -XX:+EnableWaitForParallelLoad Is Removed (JDK-8298469)
  • The MetaspaceReclaimPolicy Flag has Been Obsoleted (JDK-8302385)

废弃项

  • Deprecate GTK2 for Removal (JDK-8280031)
  • Deprecate JMX Subject Delegation and the JMXConnector.getMBeanServerConnection(Subject) Method for Removal (JDK-8298966)

重要bug修复

  • Error Computing the Amount of Milli- and Microseconds between java.time.Instants (JDK-8307466)
  • Disallow Extra Semicolons Between “import” Statements (JDK-8027682)

已知问题

  • JVM May Crash or Malfunction When Using ZGC and Non-Default ObjectAlignmentInBytes (JDK-8312749)
  • Validations on ZIP64 Extra Fields (JDK-8313765)
  • java.util.regex.MatchResult Might Throw StringIndexOutOfBoundsException on Regex Patterns Containing Lookaheads and Lookbehinds (JDK-8132995)
  • JVM May Hang When Using Generational ZGC if a VM Handshake Stalls on Memory (JDK-8311981)

其他事项

  • ObjectInputStream::readObject() Should Handle Negative Array Sizes without Throwing NegativeArraySizeExceptions (JDK-8306461)
  • File::listRoots Changed to Return All Available Drives on Windows (JDK-8208077)
  • Thread.sleep(millis, nanos) Is Now Able to Perform Sub-Millisecond Sleeps (JDK-8305092)
  • FileChannel.transferFrom Extends File if Called to Transfer Bytes to the File (JDK-8303260)
  • Clarification of the Default Charset Initialization with file.encoding (JDK-8300916)
  • java.util.Formatter May Return Slightly Different Results on double and float (JDK-8300869)
  • JVM TI ThreadStart and ThreadEnd Events Not Sent for Virtual Threads (JDK-8307399)
  • Add final Keyword to Some Static Methods (JDK-8302696)

小结

Java21主要有如下几个特性

  • JEP 430: String Templates (Preview)
  • JEP 431: Sequenced Collections
  • JEP 439: Generational ZGC
  • JEP 440: Record Patterns
  • JEP 441: Pattern Matching for switch
  • JEP 442: Foreign Function & Memory API (Third Preview)
  • JEP 443: Unnamed Patterns and Variables (Preview)
  • JEP 444: Virtual Threads
  • JEP 445: Unnamed Classes and Instance Main Methods (Preview)
  • JEP 446: Scoped Values (Preview)
  • JEP 448: Vector API (Sixth Incubator)
  • JEP 449: Deprecate the Windows 32-bit x86 Port for Removal
  • JEP 451: Prepare to Disallow the Dynamic Loading of Agents
  • JEP 452: Key Encapsulation Mechanism API
  • JEP 453: Structured Concurrency (Preview)

其中JEP 439: Generational ZGC及JEP 444: Virtual Threads应属于重磅级的特性,而JEP 430: String Templates (Preview)、JEP 431: Sequenced Collections、JEP 440: Record Patterns及JEP 441: Pattern Matching for switch则在语言表达力层面上有了增强
另外java21是继JDK 17之后最新的长期支持(LTS)版本,将获得至少8年的支持。

doc

  • JDK 21 Features
  • JDK 21 Release Notes
  • Consolidated JDK 21 Release Notes
  • Java SE 21 deprecated-list
  • The Arrival of Java 21
  • JDK 21 G1/Parallel/Serial GC changes
  • Java 21, the Next LTS Release, Delivers Virtual Threads, Record Patterns and Pattern Matching
  • JDK 21 and JDK 22: What We Know So Far
  • Java 21 New Features: “The ZGC is generational and will further improve performance for suitable applications”
  • Java 21 is Available Today, And It’s Quite the Update

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1025855.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java下打印直角三角型(另一个方向)

代码如下&#xff1a; public class MyWork {public static void main(String[] args) {int num 5;for (int i 0; i < num; i) {for (int j 0; j < i; j) {System.out.print("-");}for (int j 0; j < num - i; j) {System.out.print("*");}S…

Ubuntu 安装 CUDA 与 OPENCL

前言&#xff1a;最近需要做一些GPU并行计算&#xff0c;因而入坑CUDA和OPENCL&#xff0c;两者都有用到一些&#xff0c;刚好有点时间&#xff0c;同时记录一些学习过程&#xff0c;排掉一些坑&#xff0c;这篇是环境安装篇&#xff0c;基本跟着走就没什么问题&#xff0c;环境…

字节跳动大规模多云CDN管理与产品化实践

近日&#xff0c;火山引擎边缘云融合CDN团队负责人孙益星在LiveVideoStack Con 2023上海站围绕融合CDN团队持续建设多云CDN平台的演进过程&#xff0c;结合建设过程中面临的难点和挑战&#xff0c;介绍了融合CDN团队接下来的主要投入方向&#xff0c;分享了火山引擎在多云应用架…

tp5.1 致命错误: Call to undefined method think\Cache::get()

致命错误: 致命错误: Call to undefined method think\Cache::get() 原因&#xff1a;&#xff08;引用类错误&#xff09; thinkphp5.1中有两个Cache类&#xff1a;think\Cache和think\facade\Cache。 官方文档中说使用think\Cache&#xff0c;但实际是使用think\facade\Cac…

SQL Server数据库中了360后缀勒索病毒怎么办,勒索病毒解密数据恢复

随着互联网的发展&#xff0c;网络安全问题日益凸显&#xff0c;勒索病毒已经成为当今数字威胁中的一大主要犯罪行为之一。其中&#xff0c;360后缀勒索病毒作为一种常见的数据库攻击形式&#xff0c;对数据库的安全性提出了极大挑战。近期我们收到很多企业的求助&#xff0c;企…

RocketMQ 源码分析——NameServer

文章目录 为什么要学RocketMQ源码RocketMQ源码中的技术亮点RocketMQ 模块结构NameServer 源码分析NameServer 整体流程NameServer 启动流程加载KV配置构建NRS通讯接收路由、心跳信息定时任务剔除超时Broker NameServer设计亮点读写锁存储基于内存NameServer无状态化 为什么要学…

SpringIOC之Lifecycle 接口

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

计算机等级考试信息安全三级填空题-二

1.信息安全的五个根本属性是&#xff1a;机密性、完整性可控性、不可否认性和完整性。 2.在Windows系统中&#xff0c;查看当前已经启动的效劳列表的命令是&#xff1a;net start 3.在数据库中&#xff0c;删除表的命令是&#xff1a;DROP 4.在信息资产治理中&#xff0c;标准…

zabbix的原理与安装

一、Zabbix介绍 1、zabbix 是什么&#xff1f; zabbix是一个开源的IT基础监控软件&#xff0c;能实时监控网络服务&#xff0c;服务器和网络设备的状态&#xff0c;如网络使用&#xff0c;CPU负载、磁盘空间等&#xff0c;主要是包括数据的收集、报警和通知的可视化界面zabbi…

Java下打印1-100以内的质数

代码如下&#xff1a; public class MyWork {public static void main(String[] args) {System.out.println("100以内的质数如下&#xff1a;");for (int num 0; num < 100; num) {if (2 num) {System.out.print(num " ");continue;}for (int i 2;…

晚上弱光拍照不够清晰,学会这几招画面清晰效果好

很多小伙伴喜欢夜晚拍摄&#xff0c;然而拍摄出来的照片经常画面偏暗甚至模糊不清&#xff0c;这是怎么回事&#xff1f; 弱光环境是很多人都比较头疼的拍摄场合&#xff0c;由于光线弱曝光不好把控&#xff0c;并且还很容易出现细节性问题&#xff0c;想要将照片拍好就非常不…

全网最详细的自动化测试(Jenkins 篇)

学习 Jenkins 自动化测试的系列文章 Robot Framework 概念Robot Framework 安装Pycharm Robot Framework 环境搭建Robot Framework 介绍Jenkins 自动化测试 1. Robot Framework 概念 Robot Framework是一个基于Python的&#xff0c;可扩展的关键字驱动的自动化测试框架。 …

MongoDB【部署 02】mongodb使用配置文件启动、添加为系统服务及自启动(一个报错:[13436][NotMasterOrSecondary])

MongoDB使用配置文件启动、添加为系统服务及设置自启动 1.是什么2.下载安装启动配置2.1 下载2.2 安装2.3 配置2.4 使用配置文件启动 3.设置系统服务及自启动3.1 设置为系统服务3.2 自启动 1.是什么 【以下内容来自ChatGPT3.5】 MongoDB是一个流行的开源文档型数据库管理系统&a…

IP地址与代理IP:了解它们的基本概念和用途

在互联网世界中&#xff0c;IP地址和代理IP是两个常见但不同的概念&#xff0c;它们在网络通信、隐私保护和安全方面发挥着重要作用。本文将介绍什么是IP地址和代理IP&#xff0c;以及它们在网络中的作用和应用。 IP地址是什么&#xff1f; IP地址&#xff0c;全称为Internet…

大健康行业千城万企信用建设工作启动大会在京召开

9月19日&#xff0c;为响应商务部、中宣部、国家发改委等13个部门共同举办的“诚信兴商宣传月”活动&#xff0c;中国国际电子商务中心所属北京国富泰信用管理有限公司联合北京华商国医堂集团及旗下东方岐黄商学院&#xff0c;北京华商国医堂中医药研究院举办的共筑信用月&…

solid works草图绘制与设置零件特征的使用说明

&#xff08;1&#xff09;草图绘制 • 草图块 在 FeatureManager 设计树中&#xff0c;您可以隐藏和显示草图的单个块。您还可以查看块是欠定义 (-)、过定义 () 还是完全定义。 要隐藏和显示草图的单个块&#xff0c;请在 FeatureManager 设计树中右键单击草图块&#xff0c;…

国内券商有没有提供股票量化交易,程序化交易接口的,怎么用?

有的&#xff0c;python语言&#xff0c;免费使用&#xff0c;个人账户可开&#xff0c;直连交易所&#xff0c;行情及时准确 以前想实现股票的程序化交易门槛很高&#xff0c;要么资金实力足&#xff0c;要么技术实力强&#xff0c;小散户根本不用想&#xff0c;现在不一样了…

leetcode:剑指 Offer 17. 打印从1到最大的n位数(python3解法)

难度&#xff1a;简单 输入数字 n&#xff0c;按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3&#xff0c;则打印出 1、2、3 一直到最大的 3 位数 999。 示例 1: 输入: n 1 输出: [1,2,3,4,5,6,7,8,9]说明&#xff1a; 用返回一个整数列表来代替打印n 为正整数 题解&…

实时车辆行人多目标检测与跟踪系统(含UI界面,Python代码)

算法架构&#xff1a; 目标检测&#xff1a;yolov5 目标跟踪&#xff1a;OCSort其中&#xff0c; Yolov5 带有详细的训练步骤&#xff0c;可以根据训练文档&#xff0c;训练自己的数据集&#xff0c;及其方便。 另外后续 目标检测会添加 yolov7 、yolox&#xff0c;目标跟踪会…

单例模式(饿汉模式 懒汉模式)与一些特殊类设计

文章目录 一、不能被拷贝的类 二、只能在堆上创建类对象 三、只能在栈上创建类对象 四、不能被继承的类 五、单例模式 5、1 什么是单例模式 5、2 什么是设计模式 5、3 单例模式的实现 5、3、1 饿汉模式 5、3、1 懒汉模式 &#x1f64b;‍♂️ 作者&#xff1a;Ggggggtm &#x…