Java 19

Paylaş

Java 19 ile gelen yenilikler Virtual Threads, Structured Concurrency, Record Patterns, Foreign Function & Memory API ve diğer özellikler ile ilgili bilgiler ve kullanımı yer alıyor.

Record Patterns (Preview) – JEP 405

Java 16 sürümüyle standart olarak Java programlama diline eklenen record yapılarına Pattern özelliği eklenmiştir.

Pattern matching özelliği instanceof ile kullanıldığında ayrıca dönüşüme ihtiyaç duymadan kullanımını sağlar.

// Old code
if (o instanceof String) {
    String s = (String)o;
    ... use s ...
}

// New code
if (o instanceof String s) {
    ... use s ...
}

Aşağıdaki örnekte record ifadesini kullanımı yer almaktadır.

record Point(int x, int y) {}

static void printSum(Object o) {
    if (o instanceof Point p) {
        int x = p.x();
        int y = p.y();
        System.out.println(x+y);
    }
}

Aşağıdaki örnekte Record patterns özelliği sayesinde record içerisindeki değerlere doğrudan erişimi sağlar.

record Point(int x, int y) {}

void printSum(Object o) {
    if (o instanceof Point(int x, int y)) {
        System.out.println(x+y);
    }
}

Özelliğin iç-içe record ifadelerinde kullanımı aşağıdaki gibidir.

record Point(int x, int y) {}
enum Color { RED, GREEN, BLUE }
record ColoredPoint(Point p, Color c) {}
record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {}

İç-içe kullanılan record ifadesinin Record Patterns özelliği kullanımı aşağıdaki gibidir.

static void printColorOfUpperLeftPoint(Rectangle r) {
    if (r instanceof Rectangle(ColoredPoint(Point p, Color c),
                               ColoredPoint lr)) {
        System.out.println(c);
    }
}

Linux/RISC-V Port – JEP 422

Linux için RISC-V işlemci desteği eklenmiştir.

Foreign Function & Memory API (Preview) – JEP 424

Java 14 ile birlikte Java 15, Java 16, Java 17, Java 18 ile geliştirilmesi devam edilen Java tarafından yönetilmeyen bellek alanlarına erişimi sağlayan Foreign Function & Memory API (FFM API) geliştirilmeye devam etmektedir.

Bu sürümde jdk.incubator.foreign paketinde yer alan sınıflar java.base modülündeki java.lang.foreign paketinde yer alır.

Aşağıdaki örnekte C kütüphanesindeki radixsort fonksiyonu kullanılarak dizi sıralaması yapılmaktadır.

// 1. Find foreign function on the C library path
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle radixSort = linker.downcallHandle(
                             stdlib.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
SegmentAllocator allocator = SegmentAllocator.implicitAllocator();
MemorySegment offHeap  = allocator.allocateArray(ValueLayout.ADDRESS, javaStrings.length);
// 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 = allocator.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, '
// 1. Find foreign function on the C library path
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle radixSort = linker.downcallHandle(
                             stdlib.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
SegmentAllocator allocator = SegmentAllocator.implicitAllocator();
MemorySegment offHeap  = allocator.allocateArray(ValueLayout.ADDRESS, javaStrings.length);
// 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 = allocator.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
'); // 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

NOT: Özelliğin kullanımı için –enable-preview parametresinin derleyiciye eklenmesi gerekmektedir.

Virtual Threads (Preview) – JEP 425

Java içerisinde yer alan Thread yönetimi ve her Thread oluşturma işlemi sistem kaynaklarını fazla kullanmaktaydı.

Java 19 ile birlikte gelen Virtual Threads ile birlikte Thread yönetimi ve Thread oluşturma işlemi verimli ve daha performanslı çalışmasını sağlar.

Aşağıdaki örnekte 10 bin adet işlem Virtual Threads ile yapılmıştır.

try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  // executor.close() is called implicitly, and waits

Benzer işlem Platforma bağlı Thread ile yapıldığında işlem daha uzun sürecektir.

try (var executor = Executors.newFixedThreadPool(200)) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            return i;
        });
    });
}  // executor.close() is called implicitly, and waits

NOT: Executor Framework Thread yönetimi için kullanılır.

NOT: Özelliğin kullanımı için –enable-preview parametresinin derleyiciye eklenmesi gerekmektedir.

Vector API (Fourth Incubator) – JEP 426

Java 16 ile birlikte gelen Java 17, Java 18 ile devam Vector API geliştirilmeye devam etmektedir.

Pattern Matching for switch (Third Preview) – JEP 427

Önceki Java sürümlerinde yer alan Pattern Matching özelliğinin kullanımı genişletilmiştir.

Guarded patterns özelliği sayesinde mantıksal operatör (&&) yerine when anahtar kelimesini kullanmayı sağlar.

static void testTriangle(Shape s) {
    switch (s) {
        case null -> 
            { break; }
        case Triangle t
        when t.calculateArea() > 100 ->
            System.out.println("Large triangle");
        case Triangle t ->
            System.out.println("Small triangle");
        default ->
            System.out.println("Non-triangle");
    }
}

Özellik null değerlerinin özellik öncesi switch ifadelerine göre sonuç vermesini sağlayarak geriye uyumluluğu sağlar.

Structured Concurrency (Incubator) – JEP 428

Java içerisinde Executor Framework Thread yönetimi için kullanılır.

Aşağıdaki kod parçası çalıştırıldığında beklenmeyen durumlar oluşabilir.

Response handle() throws ExecutionException, InterruptedException {
    Future<String>  user  = esvc.submit(() -> findUser());
    Future<Integer> order = esvc.submit(() -> fetchOrder());
    String theUser  = user.get();   // Join findUser
    int    theOrder = order.get();  // Join fetchOrder
    return new Response(theUser, theOrder);
}

findUser alındığı sırada hata oluşursa fetchOrder çalışmaya devam edecek ve sistem kaynaklarını gereksiz yere kullanacaktır.

Aşağıdaki örnekte özelliğin kullanımı yer almaktadır.

Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        Future<String>  user  = scope.fork(() -> findUser());
        Future<Integer> order = scope.fork(() -> fetchOrder());

        scope.join();           // Join both forks
        scope.throwIfFailed();  // ... and propagate errors

        // Here, both forks have succeeded, so compose their results
        return new Response(user.resultNow(), order.resultNow());
    }
}

Özelliğin kullanımı için jdk.incubator.concurrent modülü ve –enable-preview parametresinin derleyiciye eklenmesi gerekmektedir.

javac --add-modules jdk.incubator.concurrent --enable-preview App.java

Özellik StructuredTaskScope sınıfında yer alan ShutdownOnFailure metodu sayesinde herhangi bir hata oluştuğunda diğer işlemi durdurarak işlemi bir bütün olarak ele almayı sağlar.

Diğer

Java 19 ile yenilikler arasında Virtual Threads ve Structured Concurrency özellikleri öne çıkmaktadır.

Java Derslerine buradan ulaşabilirsiniz.

Hayırlı günler dilerim.


Bunlarda ilgini çekebilir


LinkedIn grubuna buradan katılın.