Eğitim Portalı/Sürüm Analizi/Java 19 (Eylül 2022)
Sürüm Analizi05-java-versiyon-analizi/12-Java-19

Java 19 (Eylül 2022)

| Özellik | Değer | |---|---| | Sürüm | Java 19 (JDK 19) | | Çıkış Tarihi | 20 Eylül 2022 | | Destek Türü | Feature Release (kısa vadeli, LTS DEĞİL) | | LTS mı? | Hayır | | Tarihsel Önemi | Project Loom (Virtual Threa…

Java 19 (Eylül 2022)

Sürüm Bilgileri

ÖzellikDeğer
SürümJava 19 (JDK 19)
Çıkış Tarihi20 Eylül 2022
Destek TürüFeature Release (kısa vadeli, LTS DEĞİL)
LTS mı?Hayır
Tarihsel ÖnemiProject Loom (Virtual Threads) ilk kez preview olarak çıktı — son 20 yılın en büyük JVM eşzamanlılık değişimidir

Tarihsel Dönüm Noktası: Java 19, ileride Java 21 LTS'in damga vuracağı Virtual Threads özelliğinin halka açık ilk preview'ini içerir. Bu yüzden Java 19, "geçici bir ara sürüm" olmasının çok ötesinde bir öneme sahiptir. Bu sürüm, "thread-per-request" modelinin ölçeklenme problemine getirilen devrimsel çözümün başlangıcıdır.


Genel Bakış

Java 19, tamamı ileride Java 21 LTS'te olgunlaşacak özelliklerin bir "preview/incubator" galerisidir:

  1. JEP 425 — Virtual Threads (1. Preview) — Project Loom. EN ÖNEMLİSİ.
  2. JEP 428 — Structured Concurrency (1. Incubator) — eşzamanlı görevleri tek bir iş birimi gibi yönetme.
  3. JEP 427 — Pattern Matching for switch (3. Preview).
  4. JEP 405 — Record Patterns (1. Preview) — record'ları yıkımla (destructuring) eşleştirme.
  5. JEP 424 — Foreign Function & Memory API (1. Preview).
  6. JEP 426 — Vector API (4. Incubator).

Özellik Detayları

1. Virtual Threads (JEP 425) — 1. PREVIEW — Project Loom

İlgili dosya: VirtualThreadsPreview.java

NEDİR?

Virtual Thread (sanal iş parçacığı), JVM tarafından yönetilen, son derece hafif bir thread türüdür. İşletim sisteminin (OS) ağır thread'leriyle 1:1 eşleşmez; bunun yerine az sayıda OS thread'i (taşıyıcı / carrier thread) üzerinde çoklanır (multiplex).

NEDEN GELDİ? (Derinlemesine)

Klasik Java thread'i (platform thread), bir OS thread'inin doğrudan sarmalayıcısıdır. Her biri yaklaşık 1 MB yığın (stack) belleği tüketir ve OS kaynağı olduğundan sayıları sınırlıdır (tipik olarak birkaç bin).

Geleneksel sunucu mimarisi olan "thread-per-request" (her istek için bir thread) modelinde:

  • 10.000 eşzamanlı bağlantı = 10.000 thread = ~10 GB sadece stack belleği. Pratikte imkansız.
  • Thread'ler bir veritabanı veya HTTP çağrısında bloklandığında (blocking I/O), pahalı OS thread'i boşta bekler ama yine de kaynak tutar.

Bu duvarı aşmak için sektör reaktif programlamaya (Reactor, RxJava, CompletableFuture zincirleri) yöneldi. Ancak reaktif kod:

  • Okunması ve hata ayıklaması zordur (callback/operatör zincirleri).
  • Yığın izleri (stack trace) anlamsızlaşır.
  • try/catch, döngüler, debugger gibi temel araçlarla uyumsuzdur.

Virtual Threads bu ikilemi çözer: basit, senkron (blocking) kod yaz, ama reaktif ölçeklenebilirliği al.

NASIL ÇALIŞIR?

Bir virtual thread bloklayıcı bir işleme (örn. socket.read()) girdiğinde, JVM onu taşıyıcı OS thread'inden söker (unmount) ve taşıyıcıyı başka bir virtual thread'e verir. İşlem tamamlandığında virtual thread tekrar bir taşıyıcıya bindirilir (mount). Böylece OS thread'i hiçbir zaman boşta beklemez.

GERÇEK HAYAT ÖRNEĞİ

Bir mikroservis, gelen her isteği işlerken 3 farklı servise HTTP çağrısı yapıyor. Platform thread'lerle 200 eşzamanlı isteği zar zor kaldıran sunucu, virtual thread'lerle on binlerce isteği aynı donanımda kaldırabilir.

Java 21'deki KALICI ve çok daha derin anlatım için: 14-Java-21/VirtualThreadsKalici.java


2. Structured Concurrency (JEP 428) — 1. INCUBATOR

NEDİR?

Bir görevin alt görevlerini (eşzamanlı çalışan) tek bir mantıksal iş birimi olarak ele alma modeli. StructuredTaskScope ile alt görevler birlikte başlar, birlikte tamamlanır veya birlikte iptal edilir.

NEDEN GELDİ?

Manuel ExecutorService + Future kullanımında, alt görevlerden biri başarısız olursa diğerlerini iptal etmek, sızıntıları (leak) önlemek, hata yaymak çok zahmetlidir. Kontrol akışı dağılır ("unstructured").

ESKİ vs YENİ

// ESKİ — manuel, sızıntıya açık
ExecutorService es = Executors.newFixedThreadPool(2);
Future<String> f1 = es.submit(() -> kullaniciGetir());
Future<Integer> f2 = es.submit(() -> siparisSayisiGetir());
String k = f1.get(); int s = f2.get(); // biri patlarsa diğeri sızar

// YENİ (incubator/preview) — yapısal, otomatik iptal
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    var k = scope.fork(() -> kullaniciGetir());
    var s = scope.fork(() -> siparisSayisiGetir());
    scope.join().throwIfFailed();
    // ikisi de başarılı; biri patlarsa diğeri otomatik iptal
}

Java 21'deki gelişmiş örnek: 14-Java-21/StructuredConcurrency.java


3. Record Patterns (JEP 405) — 1. PREVIEW

İlgili dosya: RecordPatternsPreview.java

NEDİR?

Bir record'u instanceof veya switch içinde eşleştirirken bileşenlerini doğrudan değişkenlere "yıkma" (destructuring) imkanı.

NEDEN GELDİ?

Pattern matching ile bir nesnenin türünü öğrenebiliyorduk ama sonra alanlarına tek tek erişmemiz gerekiyordu. Record patterns, türü eşleştirir ve aynı anda alanları çıkarır.

ESKİ vs YENİ

record Nokta(int x, int y) {}

// ESKİ
if (nesne instanceof Nokta n) {
    int x = n.x();
    int y = n.y();
}

// YENİ (preview) — yıkımla
if (nesne instanceof Nokta(int x, int y)) {
    // x ve y doğrudan kullanılabilir
}

EVRİM

  • Java 19: 1. preview (JEP 405)
  • Java 20: 2. preview (JEP 432)
  • Java 21: KALICI (JEP 440)

Java 21'deki iç içe yıkım örneği: 14-Java-21/RecordPatternsKalici.java


4. Pattern Matching for switch (JEP 427) — 3. PREVIEW

Java 17 (1.), Java 18 (2.) sonrası üçüncü preview. Bu sürümde tamlık (exhaustiveness) ve null işleme rafine edildi. Kalıcı hali Java 21.

5. Foreign Function & Memory API (JEP 424) — 1. PREVIEW

Incubator aşamasından preview'e terfi etti. Kalıcı hali Java 22.

6. Vector API (JEP 426) — 4. INCUBATOR

SIMD hızlandırma; hâlâ incubator.


Geçiş Rehberi: Java 18 -> Java 19'da Ne Değişti?

KonuEtkiAksiyon
Virtual ThreadsPreview — devrimsel ama henüz deneysel--enable-preview ile DENEYIN, üretime almayın
Structured ConcurrencyIncubatorAPI değişebilir; sadece deneme
Record PatternsPreviewJava 21'de kalıcı olacak; öğrenin
Pattern Matching switch3. previewOlgunlaşıyor

Genel Tavsiye

Java 19'un asıl değeri: Virtual Threads ve Record Patterns'i erkenden öğrenmek. Bu özellikler Java 21 LTS'te kalıcı olacağı için, ekiplerin şimdiden tanışması büyük avantaj sağlar. Üretim hedefi olarak Java 19 yerine doğrudan Java 21 LTS planlanmalıdır.

Kod Örnekleri(2)

RecordPatternsPreview

çalıştırılabilir
RecordPatternsPreview.java
1/**
2 * JAVA 19 - RECORD PATTERNS (JEP 405) - 1. PREVIEW
3 * =================================================
4 *
5 * Bu dosya, Record Patterns'in Java 19'daki ILK preview halini gosterir.
6 * (Daha gelismis / kalici ornekler: 13-Java-20 ve 14-Java-21 klasorleri.)
7 *
8 * NEDIR?
9 *   Bir record'u eslestirirken (instanceof / switch), bilesenlerini DOGRUDAN
10 *   degiskenlere "yikma" (destructuring) imkani. Tur eslesmesi ve alan
11 *   cikarimi tek adimda olur.
12 *
13 * NEDEN GELDI?
14 *   Pattern matching (Java 16) ile turu ogrenip bir degiskene baglayabiliyorduk,
15 *   ancak alanlara yine tek tek erismek gerekiyordu. Record patterns bu adimi
16 *   ortadan kaldirir.
17 *
18 * --- DERLEME / CALISTIRMA (Java 19'da PREVIEW) ---
19 *   javac --release 19 --enable-preview RecordPatternsPreview.java
20 *   java  --enable-preview RecordPatternsPreview
21 *
22 *   NOT: Java 21'de bu ozellik KALICI oldu; orada --enable-preview gerekmez.
23 */
24public class RecordPatternsPreview {
25
26    // Basit record'lar
27    record Nokta(int x, int y) {}
28    record Cizgi(Nokta baslangic, Nokta bitis) {}
29
30    public static void main(String[] args) {
31        System.out.println("=== JAVA 19: RECORD PATTERNS (1. PREVIEW) ===\n");
32
33        Object n = new Nokta(3, 4);
34        Object c = new Cizgi(new Nokta(0, 0), new Nokta(10, 5));
35
36        eskiYontem(n);
37        yeniYontem(n);
38        icIceYikim(c);
39    }
40
41    /** ESKI: once instanceof ile tur, sonra alanlara erisim metoduyla. */
42    private static void eskiYontem(Object nesne) {
43        System.out.println("--- ESKI yontem (alanlara tek tek erisim) ---");
44        if (nesne instanceof Nokta nk) {
45            int x = nk.x();
46            int y = nk.y();
47            System.out.println("  Nokta: x=" + x + ", y=" + y);
48        }
49        System.out.println();
50    }
51
52    /** YENI: record pattern ile yikim. Tur + alan cikarimi tek satirda. */
53    private static void yeniYontem(Object nesne) {
54        System.out.println("--- YENI yontem (record pattern / yikim) ---");
55        // x ve y dogrudan burada tanimlanir
56        if (nesne instanceof Nokta(int x, int y)) {
57            System.out.println("  Nokta: x=" + x + ", y=" + y);
58        }
59        System.out.println();
60    }
61
62    /**
63     * IC ICE YIKIM (nested destructuring): Record patterns en cok burada parlar.
64     * Cizgi'nin icindeki iki Nokta'nin alanlarini tek desende cikariyoruz.
65     */
66    private static void icIceYikim(Object nesne) {
67        System.out.println("--- Ic ice yikim (nested record pattern) ---");
68        if (nesne instanceof Cizgi(Nokta(int x1, int y1), Nokta(int x2, int y2))) {
69            int dx = x2 - x1;
70            int dy = y2 - y1;
71            double uzunluk = Math.sqrt(dx * dx + dy * dy);
72            System.out.printf("  Cizgi (%d,%d)->(%d,%d), uzunluk=%.2f%n",
73                    x1, y1, x2, y2, uzunluk);
74        }
75        System.out.println();
76    }
77}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.

VirtualThreadsPreview

çalıştırılabilir
VirtualThreadsPreview.java
1import java.time.Duration;
2import java.util.concurrent.Executors;
3import java.util.concurrent.atomic.AtomicInteger;
4
5/**
6 * JAVA 19 - VIRTUAL THREADS (JEP 425) - 1. PREVIEW (Project Loom)
7 * ===============================================================
8 *
9 * Bu dosya, Virtual Threads'in Java 19'daki ILK preview halini gosterir.
10 * (Kalici ve cok daha derin anlatim icin: 14-Java-21/VirtualThreadsKalici.java)
11 *
12 * --- KAVRAMLAR ---
13 *  PLATFORM THREAD (klasik):
14 *    - Bir OS thread'inin dogrudan sarmalayicisidir.
15 *    - ~1 MB stack tuketir, OS kaynagidir, sayisi sinirlidir (~binlerce).
16 *  VIRTUAL THREAD (yeni):
17 *    - JVM tarafindan yonetilir, cok hafiftir (~birkac yuz byte baslangic).
18 *    - Az sayida "carrier" (tasiyici) OS thread uzerinde coklanir.
19 *    - Bloklayici I/O'da JVM thread'i tasiyicidan SOKER (unmount), tasiyiciyi
20 *      baska bir virtual thread'e verir. Boylece OS thread bosta beklemez.
21 *    - MILYONLARCA virtual thread olusturulabilir.
22 *
23 * --- DERLEME / CALISTIRMA (Java 19'da PREVIEW oldugu icin gerekli) ---
24 *   javac --release 19 --enable-preview VirtualThreadsPreview.java
25 *   java  --enable-preview VirtualThreadsPreview
26 *
27 *   NOT: Java 21'de bu ozellik KALICI oldu; orada --enable-preview gerekmez.
28 */
29public class VirtualThreadsPreview {
30
31    public static void main(String[] args) throws InterruptedException {
32        System.out.println("=== JAVA 19: VIRTUAL THREADS (1. PREVIEW) ===\n");
33
34        ornek1_tekVirtualThread();
35        ornek2_cokSayidaVirtualThread();
36        ornek3_executorIleVirtualThread();
37
38        System.out.println("\n=== Ozet ===");
39        System.out.println("""
40                * Virtual thread = cok hafif, JVM yonetimli thread.
41                * Bloklayici (senkron) kod yaz; reaktif olceklenebilirligi al.
42                * Java 19'da PREVIEW; Java 21'de KALICI oldu.
43                """);
44    }
45
46    /** En basit kullanim: tek bir virtual thread baslat. */
47    private static void ornek1_tekVirtualThread() throws InterruptedException {
48        System.out.println("--- Ornek 1: Tek virtual thread ---");
49
50        // Thread.ofVirtual() -> virtual thread fabrikasi
51        Thread vt = Thread.ofVirtual().name("ilk-vt").start(() ->
52                System.out.println("  Merhaba virtual thread'ten! isVirtual="
53                        + Thread.currentThread().isVirtual()));
54
55        vt.join(); // bitmesini bekle
56        System.out.println();
57    }
58
59    /**
60     * Cok sayida virtual thread: 10.000 thread. Platform thread'le bu sayi
61     * cogu sistemde OutOfMemoryError verir; virtual thread'le sorunsuzdur.
62     */
63    private static void ornek2_cokSayidaVirtualThread() throws InterruptedException {
64        System.out.println("--- Ornek 2: 10.000 virtual thread ---");
65        int adet = 10_000;
66        AtomicInteger sayac = new AtomicInteger();
67
68        Thread[] threadler = new Thread[adet];
69        for (int i = 0; i < adet; i++) {
70            threadler[i] = Thread.ofVirtual().start(() -> {
71                try {
72                    // Bloklayici bir islemi taklit et (orn. ag/DB cagrisi)
73                    Thread.sleep(Duration.ofMillis(100));
74                    sayac.incrementAndGet();
75                } catch (InterruptedException ignored) { }
76            });
77        }
78        for (Thread t : threadler) t.join();
79
80        System.out.println("  " + sayac.get() + " virtual thread tamamlandi.");
81        System.out.println("  (Platform thread ile 10.000 adet cogu makinede patlardi.)\n");
82    }
83
84    /**
85     * En yaygin uretim deseni: her gorev icin yeni bir virtual thread acan
86     * bir executor. Web sunucularda "her istek icin bir virtual thread"
87     * modelinin temeli budur.
88     */
89    private static void ornek3_executorIleVirtualThread() throws InterruptedException {
90        System.out.println("--- Ornek 3: newVirtualThreadPerTaskExecutor ---");
91
92        // try-with-resources: executor kapaninca tum gorevlerin bitmesini bekler
93        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
94            for (int i = 1; i <= 5; i++) {
95                int gorevNo = i;
96                executor.submit(() -> {
97                    System.out.println("  Gorev " + gorevNo + " calisiyor ("
98                            + Thread.currentThread() + ")");
99                    return gorevNo;
100                });
101            }
102        } // executor.close() -> tum gorevler bitene kadar bloklar
103        System.out.println();
104    }
105}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.