共计 23210 个字符,预计需要花费 59 分钟才能阅读完成。
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 办法的默认实现
此次版本的变动:
- 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
在 JDK19https://openjdk.org/jeps/425)作为第一次 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