The JDK 17 is a long-term support (LTS) version, which means it has Oracle support for many years to come. Other LTS JDKs are Java 8 and Java 11.

LTS JDKs are released every three years and non-LTS every six months. JDK 17 reached General Availability on 14 September 2021. Production-ready binaries under the GPL are available from Oracle; binaries from other vendors will follow shortly.

JDK 17 will be a long-term support (LTS) release from most vendors.

In comparison, LTS versions’ support lasts for several years, whereas the non-LTS JDKs’ support lasts only six months, ending when the next non-LTS is released. Here are the details of the fourteen JDK Enhancements Proposals (JEP) separated by new, removed and as a preview.

New Language Feature:

Sealed Classes

Sealed Classes allow API designers to specify which classes or interfaces may extend or implement a given class. Having an exhaustive list of cases to consider when modeling a problem can simplify development.

A class is sealed by applying the sealed modifier to its declaration. Then, after any extends and implements clauses, the permits the clause specifies the classes that are permitted to extend the sealed class. For example, the following declaration of Worker specifies three permitted subclasses:

public abstract sealed class Worker
     permits Empolyee, Manager { ... }

The classes specified by permits must be located near the superclass: either in the same module (if the superclass is in a named module) or in the same package (if the superclass is in the unnamed module).

Foreign Function & Memory API (Incubator)

JDK 17 introduces a much easier way to integrate with code and data outside of the Java runtime — Introduce an API(FFM) by which Java programs can interoperate with code and data outside of the Java runtime. By efficiently invoking foreign functions (i.e., code outside the JVM), and by safely accessing foreign memory (i.e., memory not managed by the JVM), the API enables Java programs to call native libraries and process native data without the brittleness and danger of JNI.

As described in the JEP 412, it replaces the Java Native Interface (JNI) with a superior, pure Java development model.

Here’s an example from the OpenJDK website:

// 1. Find foreign function on the C library path
MethodHandle radixSort = CLinker.getInstance().downcallHandle(
                           CLinker.systemLookup().lookup("radixsort"), ...);
// 2. Allocate on-heap memory to store four strings
String[] javaStrings   = { "mouse", "cat", "dog", "car" };
// 3. Allocate off-heap memory to store four pointers
MemorySegment offHeap  = MemorySegment.allocateNative(
                             MemoryLayout.ofSequence(javaStrings.length,
                                                     CLinker.C_POINTER), ...);
// 4. Copy the strings from on-heap to off-heap
for (int i = 0; i < javaStrings.length; i++) {
    // Allocate a string off-heap, then store a pointer to it
    MemorySegment cString = CLinker.toCString(javaStrings[i], newImplicitScope());
    MemoryAccess.setAddressAtIndex(offHeap, i, cString.address());
}
// 5. Sort the off-heap data by calling the foreign function
radixSort.invoke(offHeap.address(), javaStrings.length, MemoryAddress.NULL, '\0');
// 6. Copy the (reordered) strings from off-heap to on-heap
for (int i = 0; i < javaStrings.length; i++) {
    MemoryAddress cStringPtr = MemoryAccess.getAddressAtIndex(offHeap, i);
    javaStrings[i] = CLinker.toJavaStringRestricted(cStringPtr);
}
assert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"});  // true

For more deails click here.

Multiline Strings

Now instead of ugly ass String that makes you want to tear your eyes out of the skull, You can use multi line string:

public static final String MULTILINE_STRING = """
            {
                "page": {
                    "title": "Page Title",
                    "posts": [
                        {"id": "1", "name":"title1"},
                        {"id": "2", "name":"title2"},
                        {"id": "3", "name":"title3"}
                    ]
            }""";

Informative NullPointerException

Before Java 17 every time when we had a NullPointerException we need to use Debug to investigate which Object is null Lets look on this example:

Test.funcA().funcB().funcC();

If I have NullPointerException - where the hell was null? which object? Now Java 17 come to help with more information insted of the old error:

Exception in thread "main" java.lang.NullPointerException
	at com.onemancrew.Test.testNPE(Main.java:5)

we now coing to get this error:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.onemancrew.Test.funcA()" because the return value of "com.onemancrew.Test.funcB()" is null

Finally, We can know exactly what’s wrong!

Enhanced Pseudo-Random Number Generators(PENGs)

Java 17 introduces new interface types and implementation for pseudorandom number generators (PRNGs). Provide new interface types and implementations for pseudorandom number generators (PRNGs), including jumpable PRNGs and an additional class of splittable PRNG algorithms (LXM).

The goals are to make it easier to change between various PRGNs algorithms, remove duplicated code in existing PRGNs, provide better stream-based programming support and, lastly, preserve the current behavior of java.util.Random.

The below example uses the new Java 17 RandomGeneratorFactory to get the famous Xoshiro256PlusPlus PRNG algorithms to generate random integers within a specific range, 0 – 10:

RandomGenerator randomGenerator = RandomGeneratorFactory.of("Xoshiro256PlusPlus").create(999);

      System.out.println(randomGenerator.getClass());

      int counter = 0;
      while(counter<=10){
          // 0-10
          int result = randomGenerator.nextInt(11);
          System.out.println(result);
          counter++;
      }

Strongly Encapsulate JDK Internals

Many third-party libraries, frameworks, and tools are accessing the internal APIs and packages of the JDK. The Java 16, JEP 396 make the strong encapsulation by default (we are not allowed to access the internal APIs easily). However, we can still use --illegal-access to switch to the simple encapsulation to still access the internal APIs.

This JEP 403 is the successor to the above Java 16 JEP 396, and it takes one more step by removing the --illegal-access option, which means we have no ways to access the internal APIs, except for critical internal APIs such as sun.misc.Unsafe.

The Goals are to continue to improve the security and maintainability of the JDK, which is one of the primary goals of Project Jigsaw, And to encourage developers to migrate from using internal elements to using standard APIs, so that both they and their users can upgrade without fuss to future Java releases.

If you will try to use the flag param --illegal-access=warn you will get this Message:

OpenJDK 64-Bit Server VM warning: Ignoring option --illegal-access=warn; support was removed in 17.0  

Pattern Matching for switch

This JEP adds pattern matching for switch statements and expressions. Since this is a preview feature, we need to use --enable-preview option to enable it.

if…else chain:

Here you can see example of code before Java 17:

 static String formatter(Object o) {
      String formatted = "unknown";
      if (o instanceof Integer i) {
          formatted = String.format("int %d", i);
      } else if (o instanceof Long l) {
          formatted = String.format("long %d", l);
      } else if (o instanceof Double d) {
          formatted = String.format("double %f", d);
      } else if (o instanceof String s) {
          formatted = String.format("String %s", s);
      }
      return formatted;
  }

Now With Java 17, we can rewrite the above code like this:

static String formatterJava17(Object o) {
        return switch (o) {
            case Integer i -> String.format("int %d", i);
            case Long l    -> String.format("long %d", l);
            case Double d  -> String.format("double %f", d);
            case String s  -> String.format("String %s", s);
            default        -> o.toString();
        };
    }

Pattern matching and null:

With Java 17 we can test the null in switch directly. Here you can see example of code before Java 17:

  static void func(String s) {
      if (s == null) {
          System.out.println("Unknown!");
          return;
      }
      switch (s) {
          case "Java 11", "Java 17"   -> System.out.println("LTS");
          default                     -> System.out.println("Ok");
      }
  }

Now with Java 17 we can add null as case in the switch:

    static void funcJava17(String s) {
        switch (s) {
            case null                   -> System.out.println("Unknown!");
            case "Java 11", "Java 17"   -> System.out.println("LTS");
            default                     -> System.out.println("Ok");
        }
    }

Remove RMI Activation

The RMI Activation mechanism is obsolete and disused. Java 15, JEP385 deprecated the RMI Activation for removal. Now this JEP removed the RMI Activation or java.rmi.activation package.

After extensive research on popular forums such as StackOverflow and JavaRanch, and on open-source codebases, there is a strong indication that RMI activation usage is considerably small. Keeping it as part of the Java platform is costly maintenance-wise. RMI activation has been optional since Java 8.

RMI activation is an interesting feature. It instantiates remote objects on-demand, which eases the development as there is no need to handle invalid stubs. Nevertheless, it hasn’t been much used.

You can read more about it here.

Deprecate the Applet API for Removal(JPE 398)

The Java Applet API is irrelevant because most of the web-browser has removed support for Java browser plug-ins. You can read more about it here.

Deprecate the Security Manager for Removal(JPE 411)

The Security Manager dates from Java 1.0. It has not been the primary means of securing client-side Java code for many years, and it has rarely been used to secure server-side code.

Deprecate the Applet API for Removal(JPE 398)

The Applet API has become essentially irrelevant since all web browser vendors have either removed support for Java browser plug-ins or announced plans to do so. The Applet API was previously deprecated (though not for removal) in Java 9 (JEP 289) in September 2017.

#Conclusion: In this article, we found updates and new features of Java 17.

It was about time for Applet to be gone, including the Security Manager, and Java must keep up with Apple’s latest updates — No surprise there, And JEP 356 will considerably improve the overall state of PRNGs related implementation, making it easier to use.

The new API “FFM API” is interesting. From the example, it’s much more straightforward to access code and data outside of the Java runtime when compared to Java Native Interface (JNI).

Java 17, a new long-term support (LTS) release of standard Java, is now available for production use.