The JDK release train is so stable that many do not pay attention anymore! Nonetheless, the new JDK-27 release is there and quite a few things to unpack.
JEP 527: Post-Quantum Hybrid Key Exchange for TLS 1.3: enhances the security of Java applications that require secure network communication by implementing hybrid key exchange algorithms for TLS 1.3. Such algorithms defend against future quantum computing attacks by combining a quantum-resistant algorithm with a traditional algorithm. Applications that use the
javax.net.sslAPIs will benefit from these improved algorithms by default, without change to existing code.JEP 523: Make G1 the Default Garbage Collector in All Environments: makes the Garbage-First (G1) garbage collector the default collector in all environments, rather than just server environments. It worth noting that all other collectors are still available and could be specified, only default changes.
JEP 534: Compact Object Headers by Default: makes compact object headers the default object header layout in the HotSpot JVM. Compact object headers reduce object headers from 96 bits down to 64 bits on 64-bit architectures, thereby reducing heap size, improving deployment density, and increasing data locality.
JEP 536: JFR In-Process Data Redaction: enhances JDK Flight Recorder (JFR) to redact command-line arguments and the initial values of environment variables and system properties in recordings. Redact this data before it leaves the process, so that sensitive information does not leak.
The new sub-options
redact-keyandredact-argumenthave been introduced, allowing to specify one or more filters that select the command-line arguments, environment variables, and system properties to be redacted.java -XX:FlightRecorderOptions:'redact-key=confidential,redact-argument=https://*:*@*' ...
Quite a few preview and incubating (vectors!) features have been carried over from the previous releases, notably:
JEP 538: PEM Encodings of Cryptographic Objects (Third Preview): introduces an API for encoding objects that represent cryptographic keys, certificates, and certificate revocation lists into the widely-used Privacy-Enhanced Mail (PEM) transport format, and for decoding from that format back into objects. This is a preview API feature.
JEP 532: Primitive Types in Patterns, instanceof, and switch (Fifth Preview): enhances pattern matching by allowing primitive types in all pattern contexts, and extend instanceof and switch to work with all primitive types. This is a preview language feature.
JEP 531: Lazy Constants (Third Preview): introduces an API for lazy constants, which are objects that hold unmodifiable data. Lazy constants are treated as true constants by the JVM, enabling the same performance optimizations that are enabled by declaring a field final. Compared to final fields, however, lazy constants offer greater flexibility as to the timing of their initialization. This is a preview API feature.
JEP 533: Structured Concurrency (Seventh Preview): simplifies concurrent programming by introducing an API for structured concurrency. Structured concurrency treats groups of related tasks running in different threads as single units of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is a preview API feature.
JEP 537: Vector API (12th Incubator): introduces an API to express vector computations that reliably compile at run time to optimal vector instructions on supported CPUs, thus achieving performance superior to equivalent scalar computations. This is an incubating API feature.
The standard library (to my surprise at least) got only a handful of changes and bug fixes introduced, the most interesting ones are below.
JDK-8371683: TYPE_USE Annotations on a var Lambda Parameter Are Rejected: following the specification change in Java 20 (JDK-8295807), the following code should be illegal, as TYPE_USE annotation should not be applicable to variable declaration that uses
var(including lambda parameter declaration):@Retention(value=RUNTIME) @Target(value={TYPE_USE}) @interface Anno { } ... Function<Integer, String> f = (@Anno var val) -> Integer.toHexString(val);JDK-8371656: HashMap.putAll() optimizations: some optimizations in the bulk insertion methods.
JDK-8272758: Improve HttpServer to avoid partial file name matches while mapping request path to context path: the behavior of the JDK built-in com.sun.net.httpserver.HttpServer implementation, when matching an incoming request path to an
HttpContextpath, was switched from string prefix matching to path prefix matching.JDK-8210336: DateTimeFormatter predefined formatters should support short time zone offsets: predefined ISO-8601 formatters that accept zone offsets should support short zone offsets for parsing.
JDK-8377013: TimeZone.getDefault() returns obsolete id on Windows (Asia/Calcutta): the default time zone returned by TimeZone.getDefault() on Windows now reflects the latest IANA TZ database IDs, aligning with current IANA definition
JDK-8196182: ServiceLoader.iterator().hasNext()/.next() may throw a LinkageError: the ServiceLoader specifies its iterator methods to throw ServiceConfigurationError "if an error occurs locating, loading or instantiating a service provider".
JDK-8385924: GZIPInputStream.read() behaves differently on some Java versions: a new system property
jdk.util.gzip.tryReadAheadAfterTraileris introduced to allow applications to control how the java.util.zip.GZIPInputStream behaves when reading the next member in a GZIP stream.JDK-8380452: ZipOutputStream::putNextEntry(ZipEntry) throws unspecified IllegalArgumentException for unmappable entry name: updates java.util.zip.ZipOutputStream::putNextEntry(ZipEntry e) to throw ZipException instead of unspecified IllegalArgumentException when an entry name or comment cannot be encoded.
JDK-8376698: Add Spliterator tests for TreeMap sub-maps: for the
subSetfrom a java.util.TreeSet or a java.util.TreeMap::keySet, if such a set is empty, its spliterator now properly throws NullPointerException fortryAdvanceandforEachRemaining.JDK-8371748: Remove the (empty) ThreadPoolExecutor.finalize() method: the finalizer in ThreadPoolExecutor has been removed.
The java.lang.foreign.SegmentAllocator interface was improved with one new method:
The java.lang.Math got three new methods introduced:
The java.lang.StrictMath mirrored the change:
Surpring addition to java.lang.String class:
One method was added to java.math.BigDecimal class:
Quite useful improvements to java.time.format.DateTimeFormatterPatternProvider:
That was it. Let us take a look which changes went into JVM itself, including garbage collection:
JDK-8374348: -XX:AOTMode=required as alias for -XX:AOTMode=on: adds
-XX:AOTMode=requiredas an alias to-XX:AOTMode=on(the intent is to deprecate and eventually remove-XX:AOTMode=on).JDK-8359706: VM.info and hs_err_pid Logs Now Report Current Open File Descriptor: adds printing of the current open file descriptor count to the
VM.infooutput andhs_err_pidcrash logs using native OS calls.JDK-8382582: Remove the experimental JVMCI feature: removes JVMCI Compiler Interface. This is pretty disruptive change, using the Graal compiler instead of C2 is not supported anymore.
JDK-8227106: Rename -XX:InitiatingHeapOccupancyPercent to -XX:G1IHOP: only the G1 garbage collector uses the option
-XX:InitiatingHeapOccupancyPercentbut it is always available. As such, it was changed to-XX:G1IHOPfor consistency and made available only if the G1 collector is available.JDK-8363996: The UseCompressedClassPointers Option Is Now Obsolete:
UseCompressedClassPointerswas deprecated in JDK-25, made obsolete, and its maintaining code was removed as well.JDK-8373481: Removal of -noclassgc, -noverify, -verifyremote and -Xverify:none Options: the
-noclassgc,-noverify,-verifyremoteand-Xverify:nonewere deprecated in JDK-24 for removal and now are removed.JDK-8238686: G1 may waste lots of space or fail to uncommit when observing MinHeapFreeRatio during sizing after full gc: changes the default values for
MinHeapFreeRatioandMaxHeapFreeRatioflags when using the G1 garbage collector. Their new values will not affect Java heap sizing any more unless explicitly set by the user.JDK-8380590: Parallel: Improve tenuring-threshold heuristics: tries to make the heuristic bidirectional and based on observed young-gen signals. It should lower the threshold when survivor pressure squeezes eden, and raise it only after a short recovery window when young-gen commit headroom is available.
JDK-8378331: G1: WeakProcessor IsAlive and KeepAlive closures not handling humongous candidates correctly: these closures now handle humongous candidates properly to allow eager reclaim.
JDK-8373894: G1: Count evacuation-failed garbage collections in gc cpu usage: fixes one of the causes of the significant distortions in GC behavior.
JDK-8377561: Parallel: Large allocations cause Full GC storm without heap expansion
Moving on to JDK and tooling, a number of highlights here:
JDK-8296183: jndiprovider.properties contains properties pointing to non-existing classes: the
jndiprovider.propertiesfile was removed from thejava.namingmodule.JDK-8371842: Support for CLDR Version 48.2: upgrades the CLDR data in the JDK to version 48.2.
JDK-8381002: Thread dump should convert longs to json numbers if possible: changed the JSON format thread dump generated by HotSpotDiagnosticMXBean::dumpThreads API and the
jcmd Thread.dump_to_fileto convert Java longs to JSON numbers instead of strings.JDK-8378110: Add -XX: prefix to settings-file flags in RuntimeMXBean.getInputArguments(): the RuntimeMXBean::getInputArguments() method now adds the
-XXprefix for arguments passed through a settings file.JDK-8377004: Java Launcher incorrectly allows inheriting a package-private main from another package: the proper inheritance rules will be followed when detecting the main methods to invoke.
JDK-8355522: Remove the `java.locale.useOldISOCodes` system property: the property was introduced for the backward compatibility in JDK-17, deprecated in JDK-25 and now removed.
JDK-8381511: Remove Obsolete Translation Resources: removes the majority of obsolete translation resource files from the JDK.
JDK-8357439: Added Bash Autocompletion Script for the jcmd Tool: a Bash autocompletion script for the
jcmddiagnostic tool has been added.JDK-8384164: JFR: Omit command-line arguments for jdk.SystemProcess: to avoid leaking sensitive information from processes running on the same computer, the
jdk.SystemProcessevent no longer emits command-line arguments.JDK-8382740: JFR: Disable jdk.OldObjectSample event for generational ZGC: the JFR event
jdk.OldObjectSampleis disabled when using generational ZGC.JDK-8367584: Implement JEP 536: JFR In-Process Data Redaction: the JVM option
-XX:FlightRecorderOptionshas been extended with a `help` option that lists the available suboptions.java -XX:FlightRecorderOptions:help
The list of different security related fixes and enhancements is truly impressive:
JDK-8372526: Added Support for ZLIB TLS Certificate Compression: implements certificate compression in TLS 1.3 using internally supported ZLIB compression algorithm (see RFC-8879 for more details).
JDK-8364182: New jcmd Command VM.security_properties Displays Active Security Properties at Runtime:
jcmd
VM.security_properties JDK-8347938: Added Support for the Latest ML-KEM and ML-DSA Private Key Encodings: the JDK now encodes ML-KEM and ML-DSA private keys in PKCS #8 format using the DER-encoded ASN.1 CHOICE formats defined in Section 6, "Private Key Format" of RFC-9935 and Section 6, "Private Key Format" of RFC-9881. Two new security properties,
jdk.mlkem.pkcs8.encodingandjdk.mldsa.pkcs8.encoding, control the encoding used when generating new keys with a KeyPairGenerator or when translating keys with a KeyFactory.JDK-8368692: Restrict Password::readPassword from reading from System.in: introduced a new security property named
jdk.security.password.allowSystemInto control whether JVM can read password from the standard input stream.JDK-8374808: New KeyStore and KeyStoreSpi Methods to Retrieve Creation Date as an Instant: new methods have been added to the KeyStore and KeyStoreSpi classes that return the creation dates of alias entries as java.time.Instant values:
JDK-8369917: Additional Parameter Sets for HSS/LMS: the HSS/LMS signature algorithm now supports the additional parameter sets defined in RFC-9858, in addition to those originally defined in RFC-8554.
JDK-8378893: X25519 should utilize a larger limb size: the increased limb size will increase performance by reducing the amount of limb operations by ~half when using 51-bit limbs.
JDK-8384353: SHA3 AVX2 and AVX512 intrinsics and improvements: SHA-3 intrinsics have been optimized in this release for x86_64 systems that support AVX-512. The ML-KEM and ML-DSA algorithms extensively use SHA-3.
JDK-8377550: Need to keep leading zeros in TlsPremasterSecret of TLS1.3 DHKeyAgreement: TLS 1.3 key agreement has been changed to use the
Generickey algorithm for Diffie-Hellman shared secrets instead of theTlsPremasterSecretalgorithm.JDK-8373426: Removal of ffdhe6144 and ffdhe8192 from the Default List of TLS Named Groups:
ffdhe6144andffdhe8192are rarely used groups and don't need to be in the default list.
By and large, JDK-27 is not the release that brings a lot to the table. Still, for many the post-quantum cryptography could be the thing warranting the adoption. All eye towards JDK-28 now.
I πΊπ¦ stand πΊπ¦ with πΊπ¦ Ukraine.