New Features in Java 17
Java 17, released in September 2021, introduced several features and enhancements. Let us delve into Java 17 new features.
1. Restore Always-Strict Floating-Point Semantics (JEP 306)
Java Enhancement Proposal (JEP) 306, titled “Restore Always-Strict Floating-Point Semantics,” aimed to address inconsistencies in the handling of floating-point operations in Java. The proposal suggested making some adjustments to the specification to ensure that certain floating-point operations would consistently follow the IEEE 754 standard, even in cases where the hardware or the underlying JVM might provide extended precision.
The goal was to enhance the predictability and reliability of floating-point computations, especially in scenarios where strict adherence to IEEE 754 semantics was crucial.
2. Enhanced Pseudo-Random Number Generators (JEP 356)
Java Enhancement Proposal (JEP) 356 aimed to enhance the existing java.util.Random
class by introducing new interfaces and implementing new random number generators (RNGs) with improved functionality, performance, and statistical quality.
Here are some key points related to JEP 356:
- New Interfaces: The proposal introduced new interfaces, such as
RandomGenerator
andRandomGeneratorProvider
, to allow for more flexibility in plugging in different random number generators. - New Implementations: The JEP proposed the inclusion of new RNG implementations that offer improved performance and statistical properties compared to the existing
java.util.Random
class. - Additional Features: The new RNGs were expected to provide additional features, such as support for different data types, more advanced algorithms, and the ability to generate random values in parallel.
- Deprecation of Legacy Methods: The proposal suggested deprecating certain methods in the
java.util.Random
class that were considered outdated or less efficient.
Here’s a simple Java code example demonstrating the use of the new Random Generators:
import java.util.Random; public class EnhancedRandomExample { public static void main(String[] args) { // Creating an instance of the new Random Generator Random random = new Random(); // Using the enhanced methods int randomInt = random.nextInt(); double randomDouble = random.nextDouble(); boolean randomBoolean = random.nextBoolean(); // Printing the results System.out.println("Random Integer: " + randomInt); System.out.println("Random Double: " + randomDouble); System.out.println("Random Boolean: " + randomBoolean); // Generating random bytes into a byte array byte[] randomBytes = new byte[5]; random.nextBytes(randomBytes); // Printing the random bytes System.out.print("Random Bytes: "); for (byte b : randomBytes) { System.out.print(b + " "); } } }
In this example, we create an instance of the Random
class, which now uses the enhanced pseudo-random number generator introduced in Java 17. We then use the new methods nextInt()
, nextDouble()
, and nextBoolean()
to generate random values. Finally, we demonstrate the use of the nextBytes()
method to generate random bytes into a byte array.
3. New macOS Rendering Pipeline (JEP 382)
The implementation of JEP 382 introduces a new Java 2D internal rendering pipeline for macOS. This change became necessary after Apple deprecated the OpenGL API in macOS 10.14, which was previously used internally in the Swing GUI. The updated implementation now utilizes the Apple Metal API. It’s important to note that, apart from the internal engine, there have been no modifications to the existing APIs.
4. macOS/AArch64 Port (JEP 391)
In response to Apple’s long-term plan to transition its computer line from X64 to AArch64, JEP 391 focuses on porting the JDK to run on AArch64 in macOS platforms. This adaptation aligns with Apple’s strategic shift in hardware architecture.
5. Deprecate the Applet API for Removal (JEP 398)
While the deprecation of the Applet API brings a sense of nostalgia for Java developers who began their careers using this interface, the reality is that many web browsers have already dropped support for Java plugins. In acknowledgment of the API’s decreasing relevance, this version marks it for removal, despite having been deprecated since version 9.
6. Strongly Encapsulate JDK Internals (JEP 403)
JEP 403 represents a significant step in the direction of strongly encapsulating JDK internals by removing the flag –illegal-access
. With this change, the platform will simply ignore the flag. If the flag is present, the console will issue a message notifying users of the discontinuation of the flag. This enhancement ensures that JDK users are restricted from accessing internal APIs, with exceptions made for critical ones such as sun.misc.Unsafe
.
7. Java 17: Pattern Matching for Switch (Preview)
Switch statements in Java have always been powerful, but they sometimes lead to verbose and repetitive code, especially when dealing with complex conditional logic. With Pattern Matching for Switch, developers can now express intricate conditions more concisely and intuitively.
Let’s consider a simple example where we want to handle different types of shapes. In traditional switch statements, one might use instanceof
checks, but with the new pattern matching, the code becomes more elegant:
switch (shape) { case Circle c -> System.out.println("Circle with radius " + c.getRadius()); case Rectangle r -> System.out.println("Rectangle with width " + r.getWidth() + " and height " + r.getHeight()); case Square s && s.isBig() -> System.out.println("Big Square"); default -> System.out.println("Unknown shape"); }
Here, the switch statement uses patterns directly in the case labels. The code is more readable, and the intent of each case is clearer compared to traditional approaches.
7.1 Using Record Types
Pattern Matching for Switch integrates seamlessly with record types, providing a concise way to handle record instances:
record Point(int x, int y) {} // ... Point point = new Point(3, 4); switch (point) { case Point(0, 0) -> System.out.println("Origin"); case Point(x, y) -> System.out.println("Point at (" + x + ", " + y + ")"); }
This feature aligns with Java’s commitment to improving developer productivity and code readability. Developers are encouraged to explore and experiment with this preview feature in Java 17.
8. Java 17: Removal of RMI Activation – JEP 407
Java 17 marks a significant milestone in the evolution of the Java platform with the removal of RMI Activation as part of JEP 407. This removal decision reflects the changing landscape of distributed computing and the decreasing relevance of RMI Activation in modern Java applications.
RMI (Remote Method Invocation) Activation has been part of the Java platform for a long time, providing a mechanism for activating objects on demand in distributed systems. However, as technology has advanced, alternative and more modern approaches to achieve similar goals have emerged. The removal of RMI Activation aligns with the Java community’s commitment to simplifying and streamlining the platform.
Developers who have been relying on RMI Activation are encouraged to explore alternative solutions, such as Java EE technologies, microservices architectures, or other frameworks that better cater to the requirements of their distributed applications. The removal of RMI Activation does not affect the core RMI functionality, and existing RMI-based applications can continue to use RMI without activation.
9. Java 17: Sealed Class – JEP 409
Sealed classes represent a restricted form of class declaration that specifies which other classes or interfaces extend or implement them. This feature introduces a new level of control over class hierarchies, making it easier for developers to design APIs with clear and well-defined extension points.
To declare a sealed class, use the sealed
modifier along with the list of permitted subclasses. For example:
sealed class Shape permits Circle, Rectangle, Square { // Common methods and properties for all shapes }
In this example, the Shape
class is sealed, and it explicitly permits the subclasses Circle
, Rectangle
, and Square
. Only these classes are allowed to extend Shape
.
9.1 Pattern Matching with Sealed Classes
Sealed classes work seamlessly with pattern matching, providing a concise and readable way to handle different subclasses. For instance:
void processShape(Shape shape) { switch (shape) { case Circle c -> System.out.println("Processing Circle with radius " + c.getRadius()); case Rectangle r -> System.out.println("Processing Rectangle with width " + r.getWidth() + " and height " + r.getHeight()); case Square s -> System.out.println("Processing Square with side " + s.getSide()); } }
The sealed classes, in combination with pattern matching, make it easier to handle different subclasses in a switch statement without the need for a default case.
9.2 Benefits of Sealed Classes
Sealed classes offer several advantages, including enhanced code readability, improved API design, and better control over the evolution of class hierarchies. By explicitly specifying the permitted subclasses, developers can create more robust and maintainable code.
10. Java 17: Vector API (Second Incubator)
The Vector API aims to simplify the programming of vector computations, leveraging modern hardware capabilities such as SIMD (Single Instruction, Multiple Data) instructions. SIMD allows for parallel processing of multiple data elements using a single instruction, leading to improved performance for certain types of computations.
10.1 Key Features
- Expressiveness: The Vector API provides a concise and expressive syntax for vector computations, making it easier for developers to work with complex vector operations.
- Performance: By taking advantage of SIMD instructions, the Vector API can significantly enhance the performance of mathematical and scientific computations.
- Interoperability: The API is designed to seamlessly interoperate with existing libraries and code, allowing developers to integrate vector computations into their applications without major disruptions.
Below is a simple code example demonstrating the use of the Vector API (Second Incubator) introduced in Java 17 (JEP 414). This example calculates the square root of each element in an array using vector operations:
import java.util.Arrays; import java.util.Random; import java.util.stream.DoubleStream; import java.util.stream.IntStream; public class VectorAPIExample { public static void main(String[] args) { // Generate a random array of double values double[] inputArray = new Random().doubles(10_000_000).toArray(); // Using Vector API to calculate square root of each element double[] resultArray = sqrtUsingVectorAPI(inputArray); // Verify the result verifyResult(inputArray, resultArray); } private static double[] sqrtUsingVectorAPI(double[] inputArray) { int arrayLength = inputArray.length; // Create a Vector from the input array var inputVector = DoubleStream.of(inputArray).collect(VectorCollectors.ofDouble(arrayLength)); // Calculate the square root using the Vector API var resultVector = inputVector.map(Math::sqrt); // Convert the result Vector to an array double[] resultArray = resultVector.toArray(); return resultArray; } private static void verifyResult(double[] inputArray, double[] resultArray) { // Verify the result by comparing with standard library square root for (int i = 0; i 1e-9) { System.out.println("Verification failed!"); return; } } System.out.println("Verification successful!"); } }
This code uses the Vector API to calculate the square root of each element in the inputArray
. The VectorCollectors
class is used to collect the elements into a Vector
. The result is then verified by comparing it with the standard library’s Math.sqrt
function.
11. Java 17: New Release Process
Java 17 introduces a new release process aimed at providing more frequent and predictable updates to the Java platform. This change in the release cadence brings several benefits to developers, ensuring a more agile and responsive development cycle.
11.1 Key Features of the New Release Process
The new release process for Java 17 includes the following key features:
- Time-Driven: Java releases will now follow a time-driven model, with new feature releases every six months. This predictable schedule allows developers to plan and adapt to the latest Java updates more effectively.
- Feature Cadence: Features will be delivered more incrementally and frequently, providing developers with quicker access to enhancements, improvements, and new functionalities.
- Preview Features: The release process includes preview features, allowing developers to experiment with and provide feedback on upcoming functionalities before they become standard.
11.2 Benefits for Developers
The new release process offers several advantages to developers:
- Faster Innovation: Developers can benefit from a more agile release cycle, gaining access to the latest features and improvements more quickly.
- Adaptability: With a predictable release schedule, developers can plan and adjust their development and deployment strategies accordingly.
- Feedback Loop: The inclusion of preview features encourages developers to provide valuable feedback, shaping the future direction of Java development.
11.3 Community Engagement
The Java community plays a vital role in the success of the new release process. Developers are encouraged to actively participate in preview feature testing, bug reporting, and discussions to contribute to the continuous improvement of the Java platform.
12. Java 17: Other Changes
- Remove the Experimental AOT and JIT Compiler (JEP 410): Introduced in JDK 9 and JDK 10 as experimental features, the Ahead-Of-Time (AOT) compilation (JEP 295) and Just-In-Time (JIT) compiler from GraalVM (JEP-317) were features with a high cost of maintenance. Despite being introduced, they had minimal adoption. This JEP removes them from the platform, but developers can still leverage them using GraalVM.
- Deprecate the Security Manager for Removal (JEP 411): The security manager, designed to secure client-side Java code, is marked for removal due to its lack of relevance. This JEP acknowledges the changing landscape and deprecates the security manager for removal.
- Foreign Function and Memory API (Incubator) (JEP 412): The Foreign Function and Memory API allow Java developers to access code from outside the JVM and manage memory outside the heap. The goal is to replace the JNI API and improve security and performance compared to the old one. This API is part of Project Panama and has evolved through various JEPs (393, 389, 383, and 370).
13. Conclusion
In conclusion, Java 17 represents another significant milestone in the evolution of the Java programming language. With a host of new features, enhancements, and performance improvements, Java 17 continues to prioritize the needs of developers by introducing innovations such as Sealed Classes, Pattern Matching for Switch, and the Vector API’s Second Incubator. The shift towards a more frequent and predictable release cadence, as reflected in the new release process, brings agility and adaptability to the Java development cycle. Additionally, the introduction of Enhanced Pseudo-Random Number Generators and the removal of outdated components demonstrate Java’s commitment to staying relevant in the ever-evolving landscape of software development. Furthermore, the declaration of Java 17 as a Long-Term Support (LTS) release underscores Oracle’s dedication to providing a stable and well-supported platform for enterprises and developers alike. As Java 17 paves the way for more accessible and expressive programming, developers can anticipate improved performance, enhanced security, and increased flexibility, fostering a robust and vibrant ecosystem for Java applications.