Sunday, May 29, 2022

Java_18_Features - Pattern Matching for switch , Foreign Function & Memory API

This is a core language update. The change aims to enhance switch statements and expressions.

As an example, here is a Switch expression:

int numLetters = 0; Day day = Day.WEDNESDAY; switch (day) { case MONDAY, FRIDAY, SUNDAY -> numLetters = 6; case TUESDAY -> numLetters = 7; case THURSDAY, SATURDAY -> numLetters = 8; case WEDNESDAY -> numLetters = 9; default -> throw new IllegalStateException("Invalid day: " + day); }; System.out.println(numLetters);

Extending pattern matching to switch allows to test an expression against a number of patterns, each with a specific action. This way, you will be able to express complex data-oriented queries in a concise and safe way.

As an example,in the following code, the value of “o” matches the pattern Long l. Therefore, the code associated with case Long l will be executed:

Object o = 123L;String formatted = 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(); };

Foreign Function & Memory API 

The Java Platform has a significant amount of libraries to reach non-JVM platforms. For example, it is possible to reach RDBMS with JDBC Drivers. It is also possible to invoke web services (HTTP client) or serve remote clients (NIO channels), or communicate with local processes using Sockets.

However, Java still has significant pitfalls in accessing code and data on the same machine which runs outside the Java runtime. It is true that Java Native Interface (JNI) supports the invocation of native code , yet it is inadequate for many reasons:

  • Firstly, JNI involves several tedious artifacts: a Java API (to wrap native methods), a C header file derived from the Java API, and a C implementation that calls the native library of interest.
  • Then, JNI can only interoperate with libraries written in languages that adopt some calling conventions – typically C and C++..
  • Finally, JNI does not reconcile the Java type system with the C type system (e.g. Java represents data as objects while C represents data with structs)

The Foreign Function & Memory API (FFM API) defines classes and interfaces so that client code in libraries and applications can

  1. Allocate foreign memory (MemorySegment, MemoryAddress, and SegmentAllocator)
  2. Manipulate and access structured foreign memory (MemoryLayout, VarHandle),
  3. Manage the lifecycle of foreign resources (ResourceScope)
  4. Call foreign functions (SymbolLookup, CLinker, and NativeSymbol).

This API includes the FFM API in the jdk.incubator.foreign package of the jdk.incubator.foreign module.

As an example, here is Java code snippet that obtains a method handle for a C library function radixsort and then uses it to sort four strings which start life in a Java array (a few details are elided):

// 1. Find foreign function on the C library path CLinker linker = CLinker.getInstance(); MethodHandle radixSort = linker.downcallHandle( linker.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, ValueLayout.ADDRESS), ...);// 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 = implicitAllocator().allocateUtf8String(javaStrings[i]); offHeap.setAtIndex(ValueLayout.ADDRESS, i, cString); }// 5. Sort the off-heap data by calling the foreign function radixSort.invoke(offHeap, 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 = offHeap.getAtIndex(ValueLayout.ADDRESS, i); javaStrings[i] = cStringPtr.getUtf8String(0); } assert Arrays.equals(javaStrings, new String[] {"car", "cat", "dog", "mouse"}); // true
Follow on LinkedIn

You may also like

Kubernetes AWS Java Coding Question
Microservices Core Java Spring Boot
Spring Framework Kafka Miscellaneous