Another six months passed and it is about time for a new JDK release: without further ado, please meet JDK-22. The theme of this release is obviously Foreign Function & Memory API that becomes generally available after numerous preview cycles. So what else is there?
JEP-454: Foreign Function & Memory API: introduces an API by which Java programs can interoperate with code and data outside of the Java runtime. By efficiently invoking foreign functions (i.e., code outside the JVM), and by safely accessing foreign memory (i.e., memory not managed by the JVM), the API enables Java programs to call native libraries and process native data without the brittleness and danger of JNI.
By all means, Foreign Function & Memory API (or FFM shortly), was eagerly awaited. For a long time JNI was the only mechanism to access native code on JVM and it has gained pretty infamous reputation of being brittle and outdated. FFM has emerged as a (substantially) better alternative and, after many rounds of previews, the API is finalized in JDK-22.
JEP-423: Region Pinning for G1: reduces latency by implementing region pinning in G1, so that garbage collection need not be disabled during Java Native Interface (JNI) critical regions.
JEP-456: Unnamed Variables & Patterns: enhances the Java programming language with unnamed variables and unnamed patterns, which can be used when variable declarations or nested patterns are required but never used. Both are denoted by the underscore character,
_
.To be fair, the positive impact of this small language change on the readability of Java programs is paramount. Familiar to Scala developers for years, it is here for Java developers now.
if (content instanceof String s && s.startsWith("{")) { parseJson(s); } else if (content instanceof String s && s.startsWith("<")) { parseXml(s); } else if (content instanceof String _) { throw new IllegalArgumentException("The content type is not detected"); };
It becomes even more evident with records:
sealed interface Response permits NoContentResponse, ContentResponse {} record NoContentResponse(int status) implements Response {} record ContentResponse(int status, byte[] content) implements Response {} public int status(final Response response) { return switch(response) { case NoContentResponse(var status) -> status; case ContentResponse(var status, _) -> status; }; }
And lamba functions:
BiFunction<String, Number, String> f = (_, n) -> n.toString();
JEP-458: Launch Multi-File Source-Code Programs: enhances the java application launcher to be able to run a program supplied as multiple files of Java source code. This will make the transition from small programs to larger ones more gradual, enabling developers to choose whether and when to go to the trouble of configuring a build tool.
This is a logical continuation of the JEP 330: Launch Single-File Source-Code Programs, delivered in JDK-11. With this change, Java could seriously challenge the status quo of the established scripting languages.
Couple of new and refined preview language features and APIs are also made into release, just briefly mentioning them here (and we would get back to them once finalized).
JEP-457: Class-File API (Preview): provides a standard API for parsing, generating, and transforming Java class files. This is a preview API.
JEP-447: Statements before super(...) (Preview): in constructors in the Java programming language, allows statements that do not reference the instance being created to appear before an explicit constructor invocation. This is a preview language feature.
JEP-459: String Templates (Second Preview): enhances the Java programming language with string templates. String templates complement Java's existing string literals and text blocks by coupling literal text with embedded expressions and template processors to produce specialized results. This is a preview language feature and API.
JEP-460: Vector API (Seventh Incubator): introduces an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations.
JEP-461: Stream Gatherers (Preview): enhances the Stream API to support custom intermediate operations. This will allow stream pipelines to transform data in ways that are not easily achievable with the existing built-in intermediate operations. This is a preview API.
JEP-462: Structured Concurrency (Second Preview): simplifies concurrent programming by introducing an API for structured concurrency. Structured concurrency treats groups of related tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is a preview API.
JEP-463: Implicitly Declared Classes and Instance Main Methods (Second Preview): evolves the Java programming language so that students can write their first programs without needing to understand language features designed for large programs. Far from using a separate dialect of the language, students can write streamlined declarations for single-class programs and then seamlessly expand their programs to use more advanced features as their skills grow. This is a preview language feature.
JEP-464: Scoped Values (Second Preview): introduces
scoped values
, which enable managed sharing of immutable data both with child frames in the same thread, and with child threads. Scoped values are easier to reason about than thread-local variables and have lower space and time costs, especially when used in combination with Virtual Threads and Structured Concurrency. This is a preview API.
Every new JDK release comes with a long list of bugfixes, and in case of JDK-22, there are quite a few worth mentioning:
JDK-8318160: javac does not reject private method reference with type-variable receiver, which may break some existing code that inadvertently exploited this bug, for example:
import java.util.function.Function; class Test { private String asString() { return "bar"; } static <T extends Test> Function>T, String> foo() { return T::asString; } }
This code snippet won't compile in JDK-22 anymore since
Test::asString
is a private method.JDK-8225377: type annotations are not visible to javac plugins across compilation boundaries:
javac
fails to associate type annotations with TypeMirrors for some symbols loaded from the classpath, which prevents plugins from accessing those annotations across compilation boundaries.JDK-8324051: StringBuffer.repeat does not work correctly after toString() was called: when the method StringBuffer.repeat(CharSequence cs, int count) (or StringBuffer.repeat(int codePoint, int count)) is invoked with parameter
count >= 2
after StringBuffer.toString() method was invoked, it does not append the given character sequence repeatedly to the string buffer as expected.JDK-8323697: Running with -Djdk.tracePinnedThreads set can hang: the "hangs" stem from the
onPinned
method executing while the virtual thread is in a transition state (typically parking).JDK-8323430: Heap dump contains duplicate thread records for mounted virtual threads: for mounted virtual threads
HeapDumper
dumps 2HPROF_GC_ROOT_THREAD_OBJ
subrecords, one of them refers to actual stack trace/stack references, another one has empty stack trace.JDK-8322863: Thread::getStackTrace can fail with InternalError if virtual thread is timed-parked when pinned:
VirtualThread::tryGetStackTrace
doesn't handle theTIMED_PINNED
state so it's possible for Thread::getStackTrace() to throwInternalError
when invoked on a virtual thread that quickly transitions from unmounted to timed-park-while-pinned.JDK-8320145: Compiler should accept final variable in Record Pattern: according to chapter 14.30.1 of the Java Language Specification,
final
is allowed (withoutfinal
, mutating the pattern variable is valid).JDK-8319330: ExecutableElement.getReceiverType doesn't return receiver types for methods loaded from bytecode: updates
javac
's implementation of ExecutableElement::getReceiverType() and ExecutableType::getReceiverType() to allow accessing type use annotations on receiver types for methods loaded from bytecode.JDK-8318492: Http2ClientImpl should attempt to close and remove connection in stop(): ensures removal of the connection from the pool in cases where the connection is shutdown by an exception, reset, etc.
JDK-8323662: LinkedTransferQueue add and put methods call overridable offer: fixes the regression introduced by JDK-8301341 that resulted in LinkedTransferQueue::put(E e) and LinkedTransferQueue::add(E e) calling overridable LinkedTransferQueue::offer(E e) (the regression caused quite a pain for Elasticsearch and OpenSearch users).
JDK-8321220: JFR: RecordedClass reports incorrect modifiers: The modifiers value reported by RecordedClass::getModifiers() doesn't match the modifiers value provided by Class::getModifiers().
Moving off from bugs and regressions, let us take a look at the interesting new features that JDK-22 delivers across the board:
JDK-8211238: @Deprecated JFR event: adds an event to help users detect their use of deprecated methods.
JDK-8317562: [JFR] Compilation queue statistics: adds a new periodic event to monitor and output statistics for the compiler queues.
JDK-8296246: Support Unicode 15.1: adds support of the Unicode Standard version 15.1.0.
JDK-8305753: Allow JIT compilation for -Xshare:dump: makes it possible for the user to enable the JIT compiler during the CDS dump by specifying
-Xshare:dump -Xmixed
.JDK-8285368: Overhaul doc-comment inheritance: an umbrella for a number of issues related to inheritance of doc comments.
JDK-8308593: TCP_KEEPxxxx Extended Socket Options Are Now Supported on the Windows Platform: adds the support of java.net.ExtendedSocketOptions
TCP_KEEPIDLE
andTCP_KEEPINTERVAL
on Windows platforms starting from Windows 10 version 1709 and onwards, andTCP_KEEPCOUNT
starting from Windows 10 version 1703 and onwards.JDK-8318422: Allow poller threads be virtual threads: changes the Linux default poller to use virtual threads.
JDK-8310031: Parallel: Implement better work distribution for large object arrays in old gen: the Parallel GC workers limit work to their stripe and only process interesting parts of large object arrays.
JDK-8308591: JLine as the default Console provider: System::console() has changed to return a Console with enhanced editing features that improve the experience of programs that use the Console API.
JDK-8306819: Consider disabling the compiler's default active annotation processing: stops running annotation processors found on the class path by default (essentially changes annotation processing to be opt-in rather than opt-out). This is a follow up to JDK-8311073: Note if implicit annotation processing is being used (delivered in JDK-21) that began to issue a warning about implicit annotation processing.
JDK-8305104: The Old Core Reflection Implementation Has Been Removed: the new core reflection implementation has been the default since JDK-18 and the old implementation is now removed (respectively, the property
-Djdk.reflect.useDirectMethodHandle=false
to enable the old core reflection implementation becomes a no-op).
Last but not least, let us talk about the API changes (standard library) that went into this release.
JDK-8316160: sun.misc.Unsafe.shouldBeInitialized and ensureClassInitialized Are Removed
The java.io.Console got a new method:
The java.lang.Class was also touched:
A hierarchy of java.net.InetAddress classes has one new method added:
There are three new constants added to java.nio.charset.StandardCharsets class:
The interface java.nio.file.Path was enhanced with two more (default) methods:
The class javax.xml.catalog.CatalogManager now has an alternative catalog resolution method:
In scope of JDK-8302987: Add uniform and spatially equidistributed bounded double streams to RandomGenerator, the java.util.random.RandomGenerator interface got a new (default) method:
The java.util.concurrent.ForkJoinPool and java.util.concurrent.ForkJoinTask continue to improve the concurrency support in the standard library with a couple of new methods in scope of JDK-8288899: java/util/concurrent/ExecutorService/CloseTest.java failed with "InterruptedException: sleep interrupted" bugfix:
As part of JEP-454: Foreign Function & Memory API, a whole new package java.lang.foreign.* was introduced into the standard library.
JDK-8041488: Locale-Dependent List Patterns brings probably one of the most interesting additions to the standard library, in the form of a new class java.text.ListFormat, that formats or parses a list of strings in a locale-sensitive way. For example, the following snippet:
ListFormat .getInstance(Locale.US, ListFormat.Type.STANDARD, ListFormat.Style.FULL) .format(List.of("Monday", "Tuesday", "Wednesday"))
would produce a formatted string:
Monday, Tuesday, or Wednesday
From the security perspective, there are couple of notable changes to highlight (but please, do not hesitate to check out JDK 22 Security Enhancements for more details):
JDK-8318096: Introduce AsymmetricKey interface with a getParams method: adds new interface java.security.AsymmetricKey to the Java standard library.
JDK-8311596: Add separate system properties for TLS server and client for maximum chain length: provides new system properties:
jdk.tls.client.maxInboundCertificateChainLength
(when in client side, it enforces a maximum certificate chain length accepted from servers) andjdk.tls.server.maxInboundCertificateChainLength
(when in server side, it enforces a maximum certificate chain length accepted from clients).JDK-8281658: Add a security category to the java -XshowSettings option: adds a security category to the
java
's-XshowSettings
option to show settings related to security.$ java -XshowSettings:security $ java -XshowSettings:security:all $ java -XshowSettings:security:properties $ java -XshowSettings:security:providers $ java -XshowSettings:security:tls
To finish up, it will be useful to mention a few regressions that ended up in JDK-22 release, the fixes are already scheduled for the upcoming major or patch releases:
JDK-8325605: Regression in round-tripping UTF-16 strings after JDK-8311906: strings read with java.nio.file.Files::readString may return incorrect strings when decoding with a charset other than
US-ASCII
,ISO08859-1
, orUTF-8
.JDK-8327860: Java processes get killed, leaving no hs_err/stack trace on macOS 14.4: pretty nasty issue with macOS 14.4 that is affecting all Java versions from JDK 8 to 22 (for more details, please read this announcement Java users on macOS 14 running on Apple silicon systems should consider delaying the macOS 14.4 update from Oracle).
JDK-8319551: Regressions >10% in some JFR Startups: a noticeable increase in startup time can be observed when using the
-XX:StartFlightRecording
option with smaller applications.
Some may say that JDK-22 is a boring release, but I personally disagree: FFM APIs and formalizing _
usage are all but not boring features.
I πΊπ¦ stand πΊπ¦ with πΊπ¦ Ukraine.
1 comment:
Update on Java and MacOS 14.4 from Oracle: https://blogs.oracle.com/java/post/java-on-macos-14-4
Post a Comment