Eğitim Portalı/Sürüm Analizi/Java 18 (Mart 2022)
Sürüm Analizi05-java-versiyon-analizi/11-Java-18

Java 18 (Mart 2022)

| Özellik | Değer | |---|---| | Sürüm | Java 18 (JDK 18) | | Çıkış Tarihi | 22 Mart 2022 | | Destek Türü | Feature Release (kısa vadeli, LTS DEĞİL) | | LTS mı? | Hayır. Sonraki LTS Java 21'dir (Eylül 2023). | | Önceki…

Java 18 (Mart 2022)

Sürüm Bilgileri

ÖzellikDeğer
SürümJava 18 (JDK 18)
Çıkış Tarihi22 Mart 2022
Destek TürüFeature Release (kısa vadeli, LTS DEĞİL)
LTS mı?Hayır. Sonraki LTS Java 21'dir (Eylül 2023).
Önceki LTSJava 17 (Eylül 2021)
JEP Sayısı9 JEP

Önemli Not: Java 18 bir "ara sürümdür". Üretim sistemlerinde nadiren doğrudan hedeflenir; çünkü 6 ayda bir gelen feature release'lerin desteği yalnızca bir sonraki sürüme kadar (6 ay) sürer. Buna rağmen Java 18, daha sonra Java 21 LTS'te kalıcı hale gelecek özelliklerin (Pattern Matching for switch, Foreign Function & Memory API) olgunlaşma yolundaki önemli bir basamağıdır.


Genel Bakış

Java 18, görece "sakin" bir sürüm olmakla birlikte, gündelik geliştiriciyi doğrudan etkileyen çok kritik bir değişiklik getirdi: UTF-8'in tüm platformlarda varsayılan karakter kodlaması olması. Bu, yıllardır süren "Windows'ta çalışıyor, Linux'ta bozuk karakter" sınıfı hataların kökünü kurutan bir adımdır.

Bu sürümün kapsadığı başlıca özellikler:

  1. JEP 400 — UTF-8 by Default (KALICI): Varsayılan charset artık platformdan bağımsız UTF-8.
  2. JEP 408 — Simple Web Server (KALICI): jwebserver komutu ile tek satırda statik dosya sunucusu.
  3. JEP 413 — Code Snippets in Java API Documentation: Javadoc içinde @snippet etiketi.
  4. JEP 420 — Pattern Matching for switch (İkinci Preview): switch ifadelerinde desen eşleştirme.
  5. JEP 419 — Foreign Function & Memory API (İkinci Incubator): JNI'nin modern halefi.
  6. JEP 417 — Vector API (Üçüncü Incubator): SIMD donanım hızlandırma.
  7. JEP 416 — Reimplement Core Reflection with Method Handles: İçsel iyileştirme.
  8. JEP 418 — Internet-Address Resolution SPI: DNS çözümleme için eklenebilir servis.

Özellik Detayları

1. UTF-8 Varsayılan Charset (JEP 400) — KALICI

İlgili dosya: UTF8Varsayilan.java

NEDİR?

Java'da new FileReader(...), new String(byte[]), PrintStream gibi pek çok API açıkça bir charset verilmediğinde "varsayılan charset"i kullanır. Java 17 ve öncesinde bu varsayılan, işletim sisteminin ve bölge ayarının (locale) belirlediği bir değerdi:

  • Windows (Türkçe): windows-1254 veya Cp1252
  • Linux/macOS (modern): genellikle UTF-8

Java 18 ile file.encoding sistem özelliği belirtilmediğinde varsayılan her platformda UTF-8 olur.

NEDEN GELDİ?

Onlarca yıllık "benim makinemde çalışıyor" probleminin temel kaynaklarından biriydi. Bir geliştirici UTF-8 makinede yazdığı dosyayı, başka bölge ayarına sahip bir sunucuda okuduğunda Türkçe karakterler (ç, ğ, ş, ü, ö, ı) bozuluyordu. Sorun sinsiydi: kod doğru görünüyor ama çıktı ortama göre değişiyordu.

NE İŞE YARAR / NEREDE KOLAYLIK SAĞLAR?

  • Aynı kod, geliştirme makinesinde de CI sunucusunda da üretim sunucusunda da aynı sonucu üretir.
  • Charset'i her yerde elle belirtme zorunluluğu pratikte ortadan kalkar (ama yine de en iyi pratik açıkça belirtmektir).
  • Türkçe gibi ASCII dışı karakter içeren diller için davranış öngörülebilir hale gelir.

ESKİ vs YENİ

// ESKİ (Java 17 ve öncesi) — RİSKLİ: charset platforma bağlı
try (FileReader fr = new FileReader("veri.txt")) { ... }
// Windows-TR: Cp1254, Linux: UTF-8 -> aynı dosya farklı okunur!

// YENİ (Java 18+) — varsayılan her yerde UTF-8
try (FileReader fr = new FileReader("veri.txt")) { ... }
// Her platformda UTF-8

// EN İYİ PRATİK (her sürümde güvenli) — charset'i açıkça belirt
import java.nio.charset.StandardCharsets;
Files.readString(Path.of("veri.txt"), StandardCharsets.UTF_8);

GERÇEK HAYAT ÖRNEĞİ

Bir e-ticaret ekibi, ürün açıklamalarını CSV'den içe aktaran bir batch işi yazar. Geliştirici (Mac, UTF-8) testlerde sorun görmez. Üretim sunucusu (eski Windows Server, Cp1254) dosyayı içe aktarınca "Büyük Çığlık" ürünü veritabanına "Büyük Çýglýk" olarak yazılır. Java 18 ile her iki ortam da UTF-8 kullandığından bu sınıf hata kaybolur.

AVANTAJ / DEZAVANTAJ / RİSK

  • Avantaj: Taşınabilirlik, öngörülebilirlik, Türkçe içerikte güvenlik.
  • Risk (Geçişte): Eski sistemler, üretilen dosyaların önceki platform charset'i (örn. Cp1254) ile okunmasına bel bağlamış olabilir. Java 18'e geçince eski araçlar bu dosyaları yanlış okuyabilir. Geçici çözüm: -Dfile.encoding=COMPAT veya açık charset.
  • Tespit: System.out.println(Charset.defaultCharset()) çıktısını sürüm geçişinden önce/sonra karşılaştırın.

2. Simple Web Server (JEP 408) — KALICI

Detaylı anlatım: SimpleWebServer.md

NEDİR?

JDK ile birlikte gelen jwebserver komut satırı aracı ve com.sun.net.httpserver paketindeki programatik API. Tek bir komutla, içinde bulunduğunuz dizini statik dosya sunucusu olarak yayınlar.

NEDEN GELDİ?

Geliştiriciler hızlı bir statik dosya sunucusu için çoğu zaman Python'un python -m http.server'ına başvuruyordu. Java ekosisteminde böyle "pil dahil" bir araç yoktu. Eğitim, prototipleme, test ve geçici dosya paylaşımı senaryoları için hafif bir çözüm gerekiyordu.

NE İŞE YARAR?

  • Statik HTML/CSS/JS prototiplerini saniyeler içinde yayınlamak.
  • Bir REST istemcisini test ederken sahte (mock) dosyalar sunmak.
  • Eğitimde HTTP kavramlarını göstermek.

ESKİ vs YENİ

# ESKİ: Python'a bağımlılık veya tam teşekküllü bir sunucu yazmak
python3 -m http.server 8000

# YENİ (Java 18+): JDK içinde gelir
jwebserver -p 8000

GERÇEK HAYAT ÖRNEĞİ

Bir frontend ekibi, build edilmiş statik dosyaları (dist/ klasörü) hızlıca bir test cihazında göstermek ister. jwebserver -b 0.0.0.0 -p 8080 ile dosyalar anında ağ üzerinden erişilebilir.

NOT

Üretim için TASARLANMAMIŞTIR: sadece GET ve HEAD destekler, HTTPS yoktur, kimlik doğrulama yoktur. Yalnızca geliştirme/test içindir.


3. Code Snippets in Java API Documentation (JEP 413)

NEDİR?

Javadoc içinde @snippet etiketi ile kod örneklerini gömme imkanı. Eski <pre>{@code ...}</pre> yönteminin modern, doğrulanabilir ve sözdizimi vurgulu halefi.

NEDEN GELDİ?

Javadoc içindeki kod örnekleri "ölü metin"di: derlenmez, vurgulanmaz, harici dosyadan alınamazdı. Bu yüzden dokümandaki örnekler kolayca eskir ve hatalı hale gelirdi.

ESKİ vs YENİ

// ESKİ
/**
 * <pre>{@code
 *   List<String> liste = List.of("a", "b");
 * }</pre>
 */

// YENİ (Java 18+) — doğrulanabilir, vurgulanır, harici dosyadan alınabilir
/**
 * {@snippet :
 *   List<String> liste = List.of("a", "b"); // @highlight substring="of"
 * }
 */

NEREDE KOLAYLIK SAĞLAR?

Kütüphane yazarları için: örnek kodlar gerçek kaynak dosyalardan çekilebildiğinden, örnekler her zaman derlenir ve güncel kalır.


4. Pattern Matching for switch (JEP 420) — İKİNCİ PREVIEW

NEDİR?

switch ifadelerinde tür deseni (type pattern) eşleştirme. Java 17'deki ilk preview'in geliştirilmiş hali.

EVRİM (ÇOK ÖNEMLİ)

Bu özellik bir evrim hikayesinin parçasıdır:

  • Java 17: 1. preview (JEP 406)
  • Java 18: 2. preview (JEP 420) — guarded pattern sözdizimi && yerine when olarak değişti
  • Java 19: 3. preview (JEP 427)
  • Java 20: 4. preview (JEP 433)
  • Java 21: KALICI (JEP 441)

ESKİ vs YENİ

// ESKİ
String tanim;
if (nesne instanceof Integer i) tanim = "tam sayı: " + i;
else if (nesne instanceof String s) tanim = "metin: " + s;
else tanim = "bilinmeyen";

// YENİ (preview)
String tanim = switch (nesne) {
    case Integer i -> "tam sayı: " + i;
    case String s  -> "metin: " + s;
    default        -> "bilinmeyen";
};

Tam ve kalıcı kullanım örneği için Java 21 klasöründeki PatternMatchingSwitchKalici.java dosyasına bakın.


5. Foreign Function & Memory API (JEP 419) — İKİNCİ INCUBATOR

NEDİR?

JVM dışındaki yerel (native) kod ve bellekle güvenli, performanslı etkileşim. Eski JNI'nin (Java Native Interface) modern, daha güvenli halefi.

NEDEN GELDİ?

JNI kırılgan, hataya açık ve yazması zordu. C kütüphanelerini (örn. OpenSSL, SQLite, makine öğrenmesi kütüphaneleri) çağırmak büyük zahmet gerektiriyordu.

EVRİM

  • Java 14-17: Incubator (Foreign Memory)
  • Java 18: 2. incubator
  • Java 19: Preview
  • Java 21: 3. preview (JEP 442)
  • Java 22: KALICI (JEP 454)

Bu özellik Java 18'de hâlâ incubator olduğundan örnek dosya eklenmemiştir; kalıcı haline ulaşması Java 22'yi bulmuştur.


6. Vector API (JEP 417) — ÜÇÜNCÜ INCUBATOR

NEDİR?

Hesaplamaları modern CPU'ların SIMD (Single Instruction, Multiple Data) komutlarına derleyen bir API. Örneğin iki dizinin elemanlarını tek seferde paralel toplamak.

NEREDE KOLAYLIK SAĞLAR?

Bilimsel hesaplama, makine öğrenmesi, görüntü işleme, finansal modelleme gibi sayısal yoğun işlerde önemli hız artışı.


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

KonuEtkiÖnerilen Aksiyon
UTF-8 varsayılanDosya/akış okuma davranışı değişebilirCharset'i her zaman açıkça belirtin; Charset.defaultCharset() çıktısını test edin
jwebserverYeni araçGeliştirme/test akışına dahil edilebilir
Pattern matching switchHâlâ previewÜretimde kullanmayın; --enable-preview gerektirir
FFM & Vector APIIncubatorAPI'ler değişebilir; üretim için erken

Genel Tavsiye

Java 18'i doğrudan üretim hedefi yapmak yerine, Java 17 LTS'ten Java 21 LTS'e geçerken yol üzerindeki bir öğrenme/test sürümü olarak değerlendirin. Java 18'in en kalıcı mirası UTF-8 varsayılanıdır.

Kod Örnekleri(1)

UTF8Varsayilan

çalıştırılabilir
UTF8Varsayilan.java
1import java.io.IOException;
2import java.io.PrintWriter;
3import java.nio.charset.Charset;
4import java.nio.charset.StandardCharsets;
5import java.nio.file.Files;
6import java.nio.file.Path;
7
8/**
9 * JAVA 18 - UTF-8 VARSAYILAN CHARSET (JEP 400)
10 * ============================================
11 *
12 * Bu dosya, Java 18 ile gelen "UTF-8 by Default" degisikligini gosterir.
13 *
14 * NEDIR?
15 *   Java 17 ve oncesinde, charset belirtilmeden yapilan dosya/akis islemleri
16 *   isletim sisteminin "varsayilan charset"ini kullanirdi. Bu deger platforma
17 *   ve bolge ayarina (locale) gore degisirdi:
18 *     - Windows (Turkce): Cp1254 / windows-1254
19 *     - Linux/macOS (modern): UTF-8
20 *   Java 18 ile bu varsayilan HER PLATFORMDA UTF-8 oldu.
21 *
22 * NEDEN ONEMLI (TURKCE ICIN)?
23 *   ç, ğ, ş, ü, ö, ı, İ gibi karakterler ASCII disindadir. Yanlis charset ile
24 *   okunduklarinda bozulurlar ("Çığlık" -> "Çýglýk"). Java 18 bu sinifi
25 *   ortadan kaldirir cunku her ortam ayni (UTF-8) varsayilani kullanir.
26 *
27 * DERLEME / CALISTIRMA:
28 *   javac UTF8Varsayilan.java
29 *   java UTF8Varsayilan
30 *
31 *   (Preview ozellik DEGILDIR; --enable-preview gerektirmez.)
32 *
33 *   Eski davranisi (geriye uyumluluk) test etmek icin:
34 *     java -Dfile.encoding=Cp1254 UTF8Varsayilan
35 */
36public class UTF8Varsayilan {
37
38    public static void main(String[] args) throws IOException {
39
40        System.out.println("=== JAVA 18: UTF-8 VARSAYILAN CHARSET ===\n");
41
42        // 1) Mevcut varsayilan charset'i goster
43        // Java 18+ ile, file.encoding ozellikle ayarlanmadiysa bu UTF-8 doner.
44        Charset varsayilan = Charset.defaultCharset();
45        System.out.println("Bu JVM'in varsayilan charset'i : " + varsayilan);
46        System.out.println("file.encoding sistem ozelligi  : "
47                + System.getProperty("file.encoding"));
48        System.out.println("native.encoding (OS charset'i) : "
49                + System.getProperty("native.encoding")); // Java 18'de eklendi
50        System.out.println();
51
52        if (varsayilan.equals(StandardCharsets.UTF_8)) {
53            System.out.println("-> Varsayilan UTF-8. Java 18+ tipik davranisi.\n");
54        } else {
55            System.out.println("-> Varsayilan UTF-8 DEGIL (" + varsayilan
56                    + "). Muhtemelen -Dfile.encoding ile eski davranis zorlandi.\n");
57        }
58
59        // 2) Turkce icerikli bir dosya yazip okuyalim
60        Path dosya = Files.createTempFile("turkce-ornek", ".txt");
61        String turkceMetin = "Ürün: Büyük Çığlık — Şehir İstanbul, fiyat 1.299₺";
62
63        // ESKI YONTEM (RISKLI): charset belirtilmeden yazma/okuma.
64        // Java 17'de platforma bagliydi; Java 18'de her yerde UTF-8.
65        riskliYazVeOku(dosya, turkceMetin);
66
67        // EN IYI PRATIK: charset'i HER ZAMAN acikca belirt (her surumde guvenli)
68        guvenliYazVeOku(dosya, turkceMetin);
69
70        // Temizlik
71        Files.deleteIfExists(dosya);
72
73        // 3) Ozet ve gecis uyarisi
74        ozetVeUyari();
75    }
76
77    /**
78     * Charset belirtmeden yazip okur.
79     * Java 18+ ile artik her platformda UTF-8 oldugu icin guvenlidir,
80     * ANCAK eski JVM'lerde veya -Dfile.encoding ile zorlandiginda bozulabilir.
81     */
82    private static void riskliYazVeOku(Path dosya, String metin) throws IOException {
83        System.out.println("--- Yontem 1: Charset BELIRTILMEDEN (varsayilana guvenerek) ---");
84
85        // Charset'siz PrintWriter -> varsayilan charset kullanir
86        try (PrintWriter yazici = new PrintWriter(Files.newBufferedWriter(dosya))) {
87            yazici.println(metin);
88        }
89
90        // Charset'siz okuma -> yine varsayilan charset
91        String okunan = Files.readString(dosya).strip();
92        System.out.println("Yazilan : " + metin);
93        System.out.println("Okunan  : " + okunan);
94        System.out.println("Eslesti mi? " + metin.equals(okunan));
95        System.out.println();
96    }
97
98    /**
99     * Charset'i acikca UTF-8 olarak belirtir. Hangi JVM/platform olursa olsun
100     * dogru calisir. ONERILEN yontem budur.
101     */
102    private static void guvenliYazVeOku(Path dosya, String metin) throws IOException {
103        System.out.println("--- Yontem 2: Charset ACIKCA UTF-8 (ONERILEN) ---");
104
105        Files.writeString(dosya, metin, StandardCharsets.UTF_8);
106        String okunan = Files.readString(dosya, StandardCharsets.UTF_8);
107
108        System.out.println("Yazilan : " + metin);
109        System.out.println("Okunan  : " + okunan);
110        System.out.println("Eslesti mi? " + metin.equals(okunan));
111
112        // Byte seviyesinde de gosterelim: "ç" UTF-8'de 2 byte (0xC3 0xA7)
113        byte[] cBytes = "ç".getBytes(StandardCharsets.UTF_8);
114        System.out.print("'c' karakterinin UTF-8 byte'lari: ");
115        for (byte b : cBytes) {
116            System.out.printf("0x%02X ", b);
117        }
118        System.out.println("\n");
119    }
120
121    private static void ozetVeUyari() {
122        System.out.println("=== OZET ===");
123        System.out.println("""
124                * Java 18+ : varsayilan charset = UTF-8 (her platformda ayni).
125                * Avantaj  : 'benim makinemde calisiyor' sinifi charset hatalari biter.
126                * Risk     : Eski araclar uretilen dosyalari onceki OS charset'i ile
127                             okumaya bel baglamis olabilir. Gecislerde dikkat!
128                * Tavsiye  : Charset'i HER ZAMAN acikca belirtin (StandardCharsets.UTF_8).
129                             Boylece kod hangi Java surumunde olursa olsun guvenli kalir.
130                * Geri uyum: Eski davranisi gecici olarak su sekilde zorlayabilirsiniz:
131                             java -Dfile.encoding=Cp1254 SinifAdi
132                """);
133    }
134}
Çıktı yerel JDK 21 ile yakalandı — tarayıcıda JVM çalışmaz.