It’s time to welcome the much-awaited version 15 of OpenJDK. The new release has 14 new features, 2949 bug fixes and backports in total, with eight issues resolved by the BellSoft team (like Thread-local handshakes implemented for Arm32).
Let’s discuss the highlights introduced in JDK 15.
1. Production-Ready ZGC (JEP 377) and Shenandoah GC (JEP 379)
Both these garbage collectors have been changed from experimental features to product features. They are low-latency GCs. ZGC is scalable, first integrated to JDK 11; Shenandoah GC is low-time-pause and appeared in JDK 12. The collectors attempt to tackle the common problem of too long stop-the-world pauses by using colored (Z) or Brooks (Shenandoah) object pointers for efficient concurrent work. They are enabled via -XX:+UseZGC and -XX:+UseShenandoahGC command-line options, respectively. ZGC and Shenandoah GC are supported on Linux x86_64, AArch64, Windows, and macOS. Shenandoah GC has been backported to JDK 11 and will become available in version 11.0.9 mid-October. G1 will remain the default garbage collector for all JDK releases starting from version 9.
2. Text Blocks (JEP 378)
A text block is a multi-line string literal that prevents the need for most escape sequences, formats the string automatically and in an easy to predict manner. It also enables the developer to have control over the format, if they so desire. This functionality was first proposed in early 2019, targeted for JDK 12, but did not make it to the release. As a preview feature in versions 13 and 14, text blocks have changed their form a lot since. Starting from JDK 15, writing Java applications becomes ever more comfortable as these handy strings can be used to express several lines of source code and denote code written in other languages, increasing its readability. Text blocks are an excellent example of Java™ constantly evolving and a reminder for developers to use experimental features with caution, as they might end up far different from the first instance.
Below are examples of text blocks in different languages.
Scala:
object ScalaTextBlock {
def main(args: Array[String]): Unit = {
val s =
"""def printHello(): Unit = {
| println("Hello Text Block!")
|}
""".stripMargin
println(s)
}
}
/*
Output:
def printHello(): Unit = {
println("Hello Text Block!")
}
*/
Kotlin:
fun main() {
val source = """
fun printHello() =
println("Hello Text Block!")
""".trimIndent()
println(source)
}
/*
Output:
fun printHello() =
println("Hello Text Block!")
*/
Java:
public class TextBlock {
public static void main(String[] args) {
var source = """
public void printHello() {
System.out.println("Hello Text Block!");
}
""";
System.out.println(source);
}
}
/*
Output:
public void printHello() {
System.out.println("Hello Text Block!");
}
*/
3. Edwards-Curve Digital Signature Algorithm (JEP 339)
JDK 15 allows implementing cryptographic signatures based on the Edwards-Curve Digital Signature Algorithm (EdDSA). It is a modern elliptic curve signature scheme showing substantial benefits if compared to the other JDK signature schemes. For instance, at the same security level, EdDSA’s performance should improve over the Elliptic Curve Digital Signature Algorithm (ECDSA) based on native C code. It is the reason why EdDSA is rather popular and already supported in crypto libraries (OpenSSL, BoringSSL and many more). However, it will only be implemented in the SunEC provider, which would receive new Signature, KeyFactory, and KeyPairGenerator services. One of the upcoming JEPs will work on integrating EdDSA with JSSE for TLS 1.3.
4. Hidden Classes (JEP 371)
Hidden classes cannot be used directly by the bytecode of other classes. They are meant to be used through reflection, indirectly, by frameworks that generate classes at runtime. Such a class may be defined as a member belonging to an access control nest (introduced by JEP 181) and unloaded independently of others. Enabling standard APIs to define not discoverable hidden classes with a limited lifecycle allows frameworks inside and outside the JDK to generate classes that could instead define hidden classes dynamically. Since many JVM languages, such as Clojure and Groovy, rely on dynamic class generation to be flexible, this feature will improve the efficiency of every programming language implementation built on the JVM. Hidden classes serve as a replacement for sun.misc.Unsafe::defineAnonymousClass
, although they do not support its full functionality (such as constant-pool patching). The goal is to deprecate this non-standard API for complete removal in a future release.
An example of a hidden class:
import java.lang.invoke.MethodHandles;
import static be.ClassLoad.getGeneratedClassBytes;
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.NESTMATE;
import static java.lang.invoke.MethodHandles.lookup;
public class HiddenClassExample {
public static void main(String[] args) throws Exception {
byte[] bytes = getGeneratedClassBytes();
MethodHandles.Lookup lookup = lookup()
.defineHiddenClass(bytes, false, NESTMATE);
Class<?> hiddenClass = lookup.lookupClass();
System.out.println("canonical name = " + hiddenClass.getCanonicalName());
System.out.println("name = " + hiddenClass.getName());
System.out.println("isHidden = " + hiddenClass.isHidden());
Object instance = hiddenClass.getConstructors()[0].newInstance();
System.out.println("toString = " + instance.toString());
}
}
/*
Output:
canonical name = null
name = HiddenClass/0x0000000800bb1c40
isHidden = true
toString = This is hidden class!
*/
5. Remove the Solaris and SPARC Ports (JEP 381)
Given that many OpenJDK projects (including the biggest ones, like Valhalla, Loom, and Panama) need considerable changes to CPU-architecture and OS-specific code, all source code related to the Solaris OS and SPARC architecture is removed from the latest release. The ports were already deprecated in JDK 14, and their removal in this release was not unexpected. Such a measure will help the OpenJDK community concentrate efforts, move HotSpot further, and enable the use of C++14 language features for HotSpot in JDK 16 next year. Liberica JDK’s LTS versions 8 and 11 will continue supporting both Solaris and SPARC—till 2031 and 2027, respectively. The change only concerns JDK 15 and further releases.
6. Disable and Deprecate Biased Locking (JEP 374)
Biased locking is a legacy technique used in the HotSpot Virtual Machine to reduce the overhead of an uncontended lock and optimize synchronization. JDK 15 is the first release where biased locking is off by default (still enabled in LTS releases, 11 and 8). It can only be turned on if -XX:+UseBiasedLocking
is set on the command line when HotSpot is started. The reason for this JEP is that the technique happens to be precariously costly to maintain while its performance gains are less evident than they were seen before. JEP 374 follows, in a way, JEP 312 from JDK 10, where thread-local handshakes were proposed to optimize the Hotspot safepoint mechanism. Note that certain Java applications may experience a drop in performance. That is why the community has left the option of re-enabling biased locking via the command line—to mitigate regression and get insight into when it might be useful nonetheless.
Liberica JDK 15 also contains a custom feature: more root certificates since JEP 319 in JDK 10. BellSoft has added a certificate bundle from Mozilla CA Store, as Mozilla is the most trustworthy source of NSS root certificates.
You can now download the Liberica JDK 15 builds here.