In the ever-evolving landscape of software development, Java continues to solidify its position as a stalwart programming language, embraced by developers worldwide for its platform independence, portability, and robustness. With the recent unveiling of Java 21, the Java community is excited, as this latest iteration introduces a plethora of groundbreaking features and enhancements designed to streamline the development process, bolster performance, and fortify security. From the introduction of virtual threads to the preview of structured concurrency and string templates, Java 21 promises to elevate the coding experience to unprecedented heights.
The Evolution of Java: A Perpetual Journey
Java’s ascension as a preeminent programming language can be attributed to its unwavering commitment to innovation and adaptation. As software ecosystems evolve and developers face novel challenges, the Java community responds with agility, introducing features that empower coders to construct more effective applications while optimizing performance and fortifying security frameworks. This iterative approach ensures Java’s relevance and fosters a vibrant community where developers contribute their insights and suggestions through Java Enhancement Proposals (JEPs), shaping the language’s trajectory.
Exploring Features of Java 21
Java 21 is a testament to the language’s continued evolution. It introduces many features that cater to the diverse needs of developers across various domains. From enhancing interoperability with other technologies to providing more efficient alternatives to deprecated functionalities, this release encapsulates Java’s dedication to delivering a superior coding experience.
1. Virtual Threads: Unleashing Concurrent Programming Potential
Java 21 introduces virtual threads, a groundbreaking feature that promises to revolutionize concurrent programming. Traditional threading models can quickly become resource-intensive, mainly when applications create more threads than the operating system can handle. Virtual threads address this challenge by mapping Java threads to carrier threads, which manage thread operations more efficiently. This abstraction affords developers greater flexibility and control, enabling them to write concurrent code with unparalleled ease.
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { IntStream.range(0, 10_000).forEach(i -> { executor.submit(() -> { Thread.sleep(Duration.ofSeconds(1)); return i; }); }); }
In this example, the program creates 10,000 tasks using virtual threads, demonstrating the scalability and efficiency of this new feature.
2. Structured Concurrency (Preview): Streamlining Concurrent Programming
Closely tied to virtual threads, the structured concurrency feature aims to simplify concurrent programming by providing an API that treats groups of related tasks running in different threads as a single unit of work. This approach streamlines error handling, cancellation, and observability, enhancing reliability and promoting a more intuitive coding style.
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()); } }
In this example, the StructuredTaskScope
simplifies the execution of concurrent subtasks, ensuring proper error handling and propagation.
3. Scoped Values (Preview): Enhancing Thread-Safe Data Sharing
Java 21 introduces scoped values, a feature that enables the safe sharing of immutable data within and across threads. Scoped values are preferred over thread-local variables, mainly when working with numerous virtual threads, as they address design flaws such as unconstrained mutability, unbounded lifetime, and expensive inheritance.
public class WithUserSession { private final static ScopedValue<String> USER_ID = new ScopedValue.newInstance(); public void processWithUser(String sessionUserId) { ScopedValue.runWhere(USER_ID, sessionUserId, () -> processRequest()); } // ... }
In this example, the ScopedValue
allows data to be securely shared between components without resorting to method arguments, enhancing code readability and maintainability.
4. Key Encapsulation Mechanism (KEM) API: Fortifying Encryption Techniques
Java 21 introduces an API for key encapsulation mechanisms (KEM), an encryption technique that secures symmetric keys via public cryptography. This feature enables applications to leverage KEM algorithms such as RSA-KEM, ECIES, and candidate algorithms for the NIST Post-Quantum Cryptography standardization process, enhancing the security of data transmission and storage.
Java 21 provides built-in support libraries. Developers don’t need additional libraries if they use Java 21 or later.
import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PublicKey; import java.security.PrivateKey; import java.security.spec.NamedParameterSpec; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec;
5. Deprecation of the Windows 32-bit x86 Port: Embracing Modern Hardware
To align with the industry’s shift towards 64-bit computing, Java 21 deprecates the Windows 32-bit x86 port, with plans to remove it in a future release. This decision reflects the evolving hardware landscape and ensures that Java remains optimized for modern computing platforms.
6. Unnamed Classes and Instance Main Methods (Preview): Simplifying Java Learning
Java 21 introduces a preview of unnamed classes and instance primary methods, a feature designed to streamline the learning process for newcomers to the language. By allowing students to write their first Java programs without the need to understand language features designed for large projects, this feature offers a smooth on-ramp to Java, reducing the ceremonial aspects of writing simple programs.
Before Java 21, a basic Java program looked like this.
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello, World!"); } }
With Unnamed Classes and Instance Main Methods, developers can now simplify it.
void main() { System.out.println("Hello, World!"); }
This example is the Preview version. Developers who want to use this feature must change the settings in the IDE.

7. Unnamed Patterns and Variables (Preview): Enhancing Code Readability and Maintainability
Complementing the previous feature, Java 21 previews unnamed patterns and variables, which improve code readability and maintainability. Unnamed patterns match record components without stating their names or types, while unnamed variables can be initialized but not used, denoted by an underscore character (_
). This feature enhances the readability of record patterns and identifies variables that must be declared but will not be used, promoting better coding practices.
Before Java 21.
Object obj = "Hello, Java"; if (obj instanceof String s) { // Even if you don't need to use 's', you still need to declare it System.out.println("It's a string!"); }
With Unnamed Patterns (Java 21).
Object obj = "Hello, Java"; if (obj instanceof String _) { // No need to name the variable, simplifying the code System.out.println("It's a string!"); }
8. Generational ZGC: Optimizing Application Performance
Java 21 introduces generational ZGC (Z Garbage Collector), an enhancement that aims to improve application performance by maintaining separate generations for young and old objects. This approach allows for more frequent collection of young objects, reducing the risk of allocation stalls, lowering required heap memory overhead, and decreasing garbage collection CPU overhead without significantly impacting throughput.
9. Record Patterns (Preview): Enhancing Data Navigation and Processing
Building upon the record patterns feature previewed in previous Java releases, Java 21 finalizes this feature, enabling the deconstruction of record values. Record patterns and type patterns can be nested, facilitating a robust, declarative, and composable form of data navigation and processing, extending pattern-matching capabilities, and promoting more composable data queries.
// Define a simple record record Person(String name, int age) {} public class RecordPatternExample { public static void main(String[] args) { Object obj = new Person("Alice", 30); // Use record pattern with 'instanceof' if (obj instanceof Person(String name, int age)) { System.out.println("Name: " + name); System.out.println("Age: " + age); } } }
In this example, the nested record patterns allow efficient data navigation and processing, simplifying complex data operations.
10. Pattern Matching for Switch: Enhancing Control Flow Expressiveness
Java 21 finalizes the pattern matching for the switch feature, enabling switch
expressions and statements to be tested against multiple patterns, each with a specific action. This feature enhances the expressiveness and applicability of switch
statements, allowing patterns to appear in case labels, relaxing the historical null-hostility, and increasing safety by requiring pattern switch
statements to cover all potential input values.
public static void main(String[] args) { Object obj = 42; // It could be a String, Integer, Double, etc. switch (obj) { case Integer i -> System.out.println("Integer: " + i); case String s -> System.out.println("String: " + s); case Double d -> System.out.println("Double: " + d); default -> System.out.println("Unknown type"); } }
11. Vector API: Accelerating Computations
Java 21 introduces the sixth incubator of a vector API, which expresses vector computations that reliably compile to optimal vector instructions on supported CPU architectures. This API aims to achieve superior performance compared to equivalent scalar computations, offering platform agnosticism, reliable runtime compilation, and graceful degradation when vector computations cannot be fully expressed as a sequence of vector instructions.
12. Foreign Function and Memory API (Preview): Enabling Interoperability
Java 21 presents the third preview of the foreign function and memory API, which enables Java programs to interoperate with code and data outside the Java runtime. By efficiently invoking foreign functions and safely accessing foreign memory, this API allows Java programs to call native libraries and process native data without the brittleness and danger of the Java Native Interface (JNI), promoting ease of use, performance, generality, and safety.
13. Sequenced Collections (Preview): Enhancing Collections Framework
The sequenced collections feature in Java 21 introduces interfaces to represent collections with a defined encounter order. Each collection has well-defined first and last elements, providing uniform APIs for accepting first and last elements and processing elements in reverse order. This feature addresses gaps in Java’s collections framework, offering a more intuitive and powerful way to work with collections.
public static void main(String[] args) { // Create a sequenced list SequencedList<String> sequencedList = new ArrayList<>(); // Add elements to the sequenced list sequencedList.add("Apple"); sequencedList.add("Banana"); sequencedList.add("Cherry"); // Display the elements System.out.println("Original Sequenced List: " + sequencedList); // Access an element by index String secondElement = sequencedList.get(1); System.out.println("Element at index 1: " + secondElement); // Remove an element sequencedList.remove("Banana"); System.out.println("After removing Banana: " + sequencedList); // Add an element at a specific index sequencedList.add(1, "Blueberry"); System.out.println("After adding Blueberry at index 1: " + sequencedList); }
14. String Templates (Preview): Simplifying String Manipulation
Java 21 previews string templates, a feature that complements Java’s existing string literals and text blocks by coupling literal text with embedded expressions and processors. This language feature and API aim to simplify the writing of Java programs by making it easy to express strings that include values computed at runtime, enhancing readability, improving program security, retaining flexibility, and simplifying the use of APIs that accept strings written in non-Java languages.
String name = "Shaaf" String greeting = "Hello \{name}"; System.out.println(greeting); // Output: Hello Shaaf
In this example, the string template feature allows for seamless integration of expressions and literal text, enhancing code readability and maintainability.

Embracing the Future: Java’s Continued Evolution
As Java 21 continues to gain traction within the developer community, it is evident that the language’s evolution is an ongoing process driven by the collective insights and contributions of its vibrant community. With each release, Java reinforces its commitment to delivering a superior coding experience, empowering developers to construct robust, scalable, and secure applications that meet the ever-evolving demands of the software industry.
Conclusion
Java 21 represents a significant milestone in the language’s journey, introducing a myriad of features that cater to the diverse needs of developers across various domains. This release showcases Java’s unwavering dedication to innovation, performance optimization, and developer productivity, from virtual threads and structured concurrency to scoped values and enhanced security measures. As the Java community continues to grow and thrive, the language’s future remains bright, poised to shape the software development landscape for years to come.