Java 22: All in One
Rachit Mehrotra
FinTech | Senior Software Engineer | SDE 2 | Digital Banking | AVP | Regional Delivery | Building Next-Gen FinTech Applications | AI Engineer
Java 8, was released on 18 March 2014, and Java 22 is out on 19th March even though it is not released as LTS, so we have to wait for it. As per the official, Java 25 will be LTS which is expected in 2025.
So jump into what's in it for us.
JDK 22 marks the Reference Implementation of Java SE Platform version 22, outlined by JSR 397 within the Java Community Process.
As of March 19, 2024, JDK 22 has attained General Availability status. Oracle provides production-ready binaries under the GPL, with binaries from other vendors to be available shortly thereafter.
This release's features and timeline were proposed and monitored through the JEP Process, with adjustments as per the JEP 2.0 proposal. The release was executed utilizing the JDK Release Process (JEP 3).
Features:
JEP 423: Introduces Region Pinning for G1
Summary:
1. Implement region pinning in G1 to reduce latency during Java Native Interface (JNI) critical regions.
Goals:
1. Avoid thread stalling due to JNI critical regions.
2. Ensure no additional latency for garbage collection initiation during JNI critical regions.
3. Maintain current garbage collection pause times when no JNI critical regions are active.
4. Minimize garbage collection pause time regressions when JNI critical regions are active.
Motivation:
1. JNI enables interoperability with C and C++, requiring critical regions for direct pointer access to Java objects.
2. In critical regions, JVM must safeguard critical objects from relocation during garbage collection, achieved through pinning or disabling GC.
3. Current G1 approach of disabling GC during critical regions causes significant latency issues and application blocking.
Description:
1. G1 divides heap into fixed-size regions and employs generational collection.
2. Pinning regions during both major and minor collection operations to support JNI critical regions.
3. Count critical objects per region; garbage-collect regions normally if count is zero, otherwise, consider region pinned.
4. During major collection, do not evacuate pinned regions; during minor collection, promote pinned regions to the old generation.
Alternatives:
1. Copy critical objects to C heap during critical regions; inefficient.
2. Pin objects individually; higher overhead compared to region pinning.
Testing:
1. Functional tests and benchmarking to ensure performance meets objectives.
Risks and Assumptions:
1. Assume JNI critical regions will continue to be used sparingly and briefly.
2. Risk of heap exhaustion if many regions are pinned simultaneously; mitigated by observing Shenandoah GC's approach.
JEP 447: Allows Statements before super
Summary:
1. Allow statements unrelated to the instance being created to appear before explicit constructor invocations in Java constructors, introducing a preview language feature.
Goals:
1. Enhance developers' flexibility in expressing constructor behavior, facilitating the natural placement of logic currently handled by auxiliary static methods or intermediate constructors.
2. Maintain the current order of constructors' execution during class instantiation, preventing subclass constructor code from interfering with superclass instantiation.
3. Ensure compatibility with the Java Virtual Machine without necessitating any changes.
Motivation:
1. Subclasses inherit functionality from superclasses, necessitating proper initialization of superclass fields before subclass fields.
2. Existing constraints on constructor syntax limit developers' ability to perform tasks such as argument validation, preparation, and sharing within constructors.
Description:
1. Modify constructor body grammar to allow block statements preceding explicit constructor invocations.
2. Introduce the concept of a pre-construction context, permitting code execution before explicit constructor invocations while disallowing access to the instance being constructed.
3. Specify cases where access to the instance being constructed is prohibited, including unqualified 'this' expressions and qualified field accesses or method invocations with 'super'.
4. Permit return statements in constructor epilogues but prohibit them in prologues.
5. Exception throwing is allowed in prologues, often used in fail-fast scenarios.
6. Ensure compatibility with record and enum class constructors, retaining existing restrictions but allowing statements before explicit constructor invocations.
Testing:
1. Validate compiler changes with existing unit tests and additional positive and negative test cases.
2. Compile JDK classes with both previous and updated compiler versions to verify bytecode consistency.
Risks and Assumptions:
1. Proposed changes are source- and behavior-compatible, expanding legal Java programs while preserving existing ones.
2. Transition may cause temporary disruptions as tools in the Java ecosystem adapt to the modified language requirements.
Dependencies:
1. Compatibility relies on the JVM's ability to verify and execute code preceding constructor invocations without referencing the instance being constructed.
2. No alterations to the Java Virtual Machine Specification are needed, as current JVM capabilities already support flexible constructor handling.
JEP 454: Introduces Foreign Function & Memory API
The FFM (Foreign Function & Memory) API in Java aims to address the challenges faced by developers when interacting with non-Java resources, specifically focusing on off-heap memory management and calling foreign functions. Here's a breakdown of the key components and concepts of the FFM API:
1. Foreign Memory Management:
- The FFM API introduces the concept of MemorySegment, which represents a contiguous region of memory. These segments can be allocated from different sources, such as off-heap memory, mapped memory, or existing on-heap Java arrays or buffers.
- Memory segments are managed within arenas, which control their allocation and deallocation. Arenas can have different lifetimes, ranging from global (unbounded) to confined (bounded by the scope of the arena). This allows developers to control when memory is deallocated, ensuring both safety and performance.
2. Structured Access to Memory:
- MemoryLayout is introduced to describe the structure of data within memory segments. This allows developers to define complex data structures in a declarative manner, reducing the need for manual calculations of memory offsets.
领英推荐
- Variable handles (`VarHandle`) provide a way to access and manipulate data within memory segments based on the defined memory layout. This enables safer and more efficient access to structured data.
3. Foreign Function Invocation:
- The Linker interface facilitates the invocation of foreign functions from Java code. It allows Java code to interact with native libraries by providing method handles for downcalls (calls from Java to native code) and upcalls (calls from native code back to Java).
- Symbol lookup mechanisms (`SymbolLookup`) are provided to locate functions within native libraries, enabling the dynamic linking of foreign functions.
- The native linker, obtained through Linker.nativeLinker(), supports various platforms and calling conventions, ensuring compatibility with native libraries across different environments.
4. Example Usage:
- The API is demonstrated through an example scenario where a Java application sorts strings using a foreign function (`radixsort`) from a C library. The example showcases memory allocation, data copying between Java and native memory, and invocation of the foreign function using the FFM API.
5. Segment Allocators:
- Segment allocators provide a flexible mechanism for memory allocation, allowing developers to choose appropriate strategies based on their specific requirements. This includes slicing allocators for efficient reuse of memory segments and custom arenas for tailored memory management.
Overall, the FFM API aims to provide Java developers with a comprehensive and safe way to interact with non-Java resources, addressing the limitations and complexities associated with existing approaches such as JNI. By offering a unified interface for both memory management and foreign function invocation, the API simplifies the development of performance-critical applications that rely on off-heap memory and native libraries.
JEP 456: Unnamed Variables & Patterns
The proposal aims to enhance the Java programming language with unnamed variables and unnamed patterns denoted by the underscore character (_). These features were previewed in JDK 21 via JEP 443, titled "Unnamed Patterns and Variables," and the proposal suggests finalizing this feature without changes.
Goals:
1. Capture developer intent regarding unused bindings or lambda parameters to clarify programs and reduce error opportunities.
2. Improve maintainability by identifying unused variables that must be declared, such as in catch clauses.
3. Allow multiple patterns in a single case label without declaring any pattern variables to improve readability.
4. Improve the readability of record patterns by eliding unnecessary nested type patterns.
Non-Goals:
1. Allowing unnamed fields or method parameters.
2. Altering the semantics of local variables in definite assignment analysis.
Motivation:
- Developers often declare variables they don't intend to use, leading to clutter and potential errors.
- Unused variables occur in various scenarios, including side-effect focused code, exception handling, and lambda expressions.
- Unused pattern variables in type patterns can clutter code and reduce readability, especially in nested patterns.
Description:
- Unnamed variables and pattern variables are denoted by the underscore character (_).
- Unnamed variables can be used in local variable declarations, catch blocks, lambda expressions, etc., without providing a name.
- Unnamed pattern variables can appear in type patterns, allowing for cleaner code in switch blocks and instanceof operations.
- Multiple patterns in a case label are allowed, but none of them can declare pattern variables.
- The unnamed pattern matches anything but declares and initializes nothing, improving code readability in complex data extraction scenarios.
Risks and Assumptions:
- Assumes little actively-maintained code uses underscore as a variable name.
- Developers may face compile-time errors if migrating from older versions of Java where underscore was used as an identifier.
- Expectation for static analysis tools to understand the new role of underscore and avoid flagging non-use of unnamed variables.
Alternatives:
- The proposal mentions the possibility of defining unnamed method parameters but notes potential specification and tooling challenges.
- JEP 302 explored unused lambda parameters and identified the role of underscore, but this JEP focuses specifically on addressing unused lambda parameters without covering other issues explored in JEP 302.
JEP 459: String Templates
The desire for a safer, more intuitive string composition mechanism in Java, akin to interpolation in other languages, is certainly understandable. While there's no built-in feature in Java as of my last update in January 2022, there are ways to achieve similar functionality using libraries or custom solutions.
One approach is to use a library like Apache Velocity or FreeMarker, which are template engines commonly used in Java. These libraries allow you to define templates with placeholders for dynamic values, which are then replaced at runtime. This approach provides safety by separating the template structure from the data, reducing the risk of injection attacks.
Here's an example of how you could use Apache Velocity for string composition:
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import java.io.StringWriter;
public class Main {
public static void main(String[] args) {
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
VelocityContext context = new VelocityContext();
context.put("name", "Joan Smith");
context.put("phone", "555-123-4567");
context.put("address", "1 Maple Drive, Anytown");
StringWriter writer = new StringWriter();
velocityEngine.evaluate(context, writer, "", """
{
"name": "$name",
"phone": "$phone",
"address": "$address"
}
""");
String json = writer.toString();
System.out.println(json);
}
}
This approach allows you to define your JSON template separately from the data, providing a safer and more organized way to compose strings.
Alternatively, you could create your own utility method or class to handle string interpolation with proper escaping and validation. This would allow you to tailor the solution to your specific needs and security requirements.
While these solutions may add a bit more complexity compared to simple string concatenation or interpolation, they offer the advantage of increased safety and maintainability, which can be crucial for applications dealing with sensitive data or external input.
JEP 461: Stream Gatherers
Summary:
The proposal aims to enhance the Stream API in Java to support custom intermediate operations, allowing for more flexibility and expressiveness in stream pipelines. This feature introduces the concept of "gatherers" as user-defined entities to transform stream elements in various ways. Gatherers can perform one-to-one, one-to-many, many-to-one, or many-to-many transformations, and can track state to influence transformation decisions. They also support parallel execution.
The key components of this proposal include:
1. Stream::gather(Gatherer): A new intermediate stream operation that processes elements using a user-defined gatherer.
2. Gatherer Interface: Defines four functions to work together: initializer, integrator, combiner, and finisher.
3. Built-in Gatherers: Includes fold, mapConcurrent, scan, windowFixed, and windowSliding gatherers in the java.util.stream .Gatherers class.
4. Parallel Evaluation: Gatherers can be evaluated in parallel with or without a combiner function.
5. Composing Gatherers: Gatherers can be composed using the andThen(Gatherer) method.
6. Example Usage: Examples demonstrate how to use gatherers for various stream processing tasks, such as detecting suspicious changes in a stream of temperature readings or grouping elements into fixed-size windows.
The proposal emphasizes the need for flexibility and expressiveness in stream processing, especially for complex tasks that cannot be easily expressed with existing intermediate operations. It acknowledges that while the use of custom gatherers may require more verbose code compared to built-in operations, it offers greater flexibility and customization options. The proposal also introduces several built-in gatherers to handle common stream processing tasks.
Risks and assumptions include the potential complexity of defining and using custom gatherers, the possibility of revising the set of built-in gatherers based on feedback, and the decision not to add new intermediate operations to the Stream class for each built-in gatherer defined.
Overall, the proposal aims to make stream processing in Java more powerful and versatile, catering to a wider range of use cases and scenarios.
// Import necessary classes
import java.util.List;
import java.util.stream.Collectors;
public class Java22Features {
public static void main(String[] args) {
// 1. Unnamed variables for unused elements (final)
List<String> names = List.of("Alice", "Bob", null);
for (String name : names) {
System.out.println(name); // Prints Alice, Bob (null is ignored)
}
// 2. Launch multi-file source-code programs (final)
// This code can be directly run without prior compilation (assuming other files exist)
useMathLibrary.calculateArea(5, 3); // Calls function from another .java file (not shown here)
// 3. Stream gatherers (preview) - concise data collection
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
.filter(n -> n % 2 == 0)
.collect(Collectors.toList()); // Concise way to collect filtered elements
System.out.println(evenNumbers); // Prints [2, 4]
// 4. Foreign Function & Memory API (final) - interacting with external code (complex, not shown here)
// This feature is powerful but requires more understanding for safe usage.
}
}
Subscribe to this newsletter. Stay tuned for future updates.