Java 25 LTS: Geliştirici Gözüyle Pratik Rehber
Beklenen oldu: Java SE 25 yayımlandı. Üstelik Java’nın 30. yılına denk gelen bir Long-Term Support (LTS) sürümü. Üretimde yıllarca güvenle kullanabileceğiniz, verimlilik ve performans odaklı bir paket geliyor.
Bu yazıda, geliştirici gözüyle “işe yarayan” yenilikleri kısa notlar ve ufak örneklerle toparladım.
TL;DR
- LTS: Üretim için güvenli hedef.
- Dil: Universal generics (primitive koleksiyonlar), esnek constructor gövdeleri, kompakt source + instance
main. - Concurrency: Structured Concurrency ve Scoped Values ile daha temiz bağlam yönetimi.
- Performans/GC: Compact Object Headers, Generational Shenandoah — açmadan önce ölçün.
- Startup & Observability: AOT profilleriyle daha hızlı ısınma; JFR CPU time + cooperative sampling ile daha doğru profil.
Dil ve Kütüphane: Daha Yalın, Daha İfade Gücü Yüksek
Universal Generics (JEP 488, preview): Artık List<int> de var
Yılların konusu gerçeğe dönüştü: generics artık primitive tiplerle de çalışıyor. List<Integer> yerine List<int> yazabiliyorsunuz; boxing/unboxing yükü kalkıyor, bellek ve hız kazanıyorsunuz.
Öncesi
List<Integer> numbers = new ArrayList<>();
numbers.add(10); // boxing
int first = numbers.get(0); // unboxing
Java 25 ile
List<int> numbers = new ArrayList<>();
numbers.add(10); // boxing yok
int first = numbers.get(0);
JVM, primitive’lere özel yoğun (dense) temsillerle çalışarak veri-yoğun işlerde ciddi kazanç sağlıyor.
Esnek Constructor Gövdeleri (JEP 513): Doğrulama artık başta
Constructor’ların super(...)/this(...) ile başlama zorunluluğu gevşedi. super() çağrısından önce validation ve hazırlık yapabiliyorsunuz.
public class Square extends Rectangle {
public Square(Color color, int area) {
if (area < 0) throw new IllegalArgumentException();
double side = Math.sqrt(area);
super(color, side, side);
}
}
Daha doğal akış, daha az yardımcı metot, daha net hata mesajları.
Compact Source Files & Instance main (JEP 512): Seremoni azaldı
Küçük programlar için public static void main(String[] args) zorunluluğu kalktı; instance main yazabiliyorsunuz. Hatta sınıf yazmadan compact source ile script gibi çalıştırmak mümkün.
void main() {
IO.println("Hello world!");
}
Öğrenme eğrisi düşüyor; prototipleme hızlanıyor.
Module Import Declarations (JEP 511): Tek satırda geniş import
Bir modülün tüm public API’sını tek satırla içeri alabilirsiniz:
import module java.base;
Özellikle eğitim/örneklerde temizlik sağlıyor.
Primitive Patterns instanceof/switch (JEP 507, 3. preview)
Pattern matching artık primitive’ler için de geçerli. Dönüşüm güvenli, kod sade.
double v = 42.0;
switch (v) {
case byte b -> System.out.println("byte: " + b);
case int i -> System.out.println("int: " + i);
case double d -> System.out.println("double: " + d);
}
Stable Values API (JEP 502, preview): Esnek “bir kez ata” sabitler
StableValue tek seferde atomik atanıp sonra değişmez kalan bir tutucu. final alanların “constructor’da set etme” kısıtını esnetiyor; lazy initialization için şık bir alternatif.
class OrderController {
private final StableValue<Logger> logger = StableValue.of();
Logger getLogger() {
return logger.orElseSet(() -> Logger.create(OrderController.class));
}
}
Concurrency: Daha Sağlam Paralellik
Structured Concurrency (JEP 505, 5. preview)
İlişkili işler tek bir kapsamda yönetiliyor; hata/iptal/sonuç toplama işleri sadeleşiyor. scope.join() artık sonuç döndürüyor.
public WeatherResponse fastest(Location loc) throws InterruptedException {
var joiner = Joiner.anySuccessfulResultOrThrow();
try (var scope = StructuredTaskScope.open(joiner)) {
scope.fork(() -> s1.getWeather(loc));
scope.fork(() -> s2.getWeather(loc));
scope.fork(() -> s3.getWeather(loc));
return scope.join(); // ilk başarılı sonucu döndürür
}
}
Scoped Values (JEP 506): ThreadLocal’a temiz ve hızlı alternatif
Çağrı zinciri ve alt iş parçacıklarına immutably bağlam geçirirsiniz.
public static final ScopedValue<User> CURRENT_USER = ScopedValue.newInstance();
ScopedValue.where(CURRENT_USER, user).run(() -> {
handleRequest(); // parametre taşımadan bağlama erişir
});
Sanal thread’lerle birlikte parlıyor; yarış koşullarını tasarımdan siliyor.
Performans, Bellek, VM: “Aç ve unut” hızlar
Compact Object Headers (JEP 519): Daha küçük nesneler
64-bit’te başlık 64 bite indi. Nesne yoğun uygulamalarda yığın kullanımı azalıyor, cache locality iyileşiyor.
java -XX:+UseCompactObjectHeaders MyApp
Generational Shenandoah (JEP 521): Düşük duraklama + daha yüksek throughput
Shenandoah’ın generational modu artık üretim seviyesinde.
java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational MyApp
Gecikmeye duyarlı servislerde güçlü bir seçenek.
AOT Profilleri (JEP 514 & 515): Daha hızlı startup/ısınma
Eğitim koşusundan AOT cache çıkar, prod’da kullanırsınız.
# profil çıkar
java -XX:AOTCacheOutput=app.aot MyApplication
# prod’da yükle
java -XX:AOTCache=app.aot MyApplication
Method profiling verileriyle JIT baştan daha isabetli derleme yapar.
Vector API (JEP 508, incubator)
SIMD’e derlenen vektörleştirilmiş hesaplamalar için olgunlaşmaya devam ediyor.
32-bit x86 artık yok (JEP 503)
Kod tabanı sade, modern hedeflere odak.
Observability: JFR’la daha isabetli teşhis
JFR CPU Time Profiling (JEP 509, experimental)
Duvar saati değil, gerçek CPU time ölçümü. Yoğun sistemlerde sıcak noktaları daha doğru yakalar.
JFR Cooperative Sampling (JEP 518)
Örnekleme güvenli noktalarda; daha düşük etki, daha tutarlı yığın izleri.
JFR Method Timing/Counting (JEP 520)
Kod enstrüman etmeden belirli method’ların süre ve frekansını izleyebilirsiniz (bayraklar/JFR config/jcmd/JMX ile).
Güvenlik & Kripto
PEM Encoding API (JEP 470, preview)
Anahtar/sertifika/CRL için yerleşik PEM encode/decode. Harici kütüphaneye bağımlılık azalıyor.
Key Derivation Function API (JEP 510)
javax.crypto altında HKDF vb. KDF’ler için standart arayüz.
KDF kdf = KDF.getInstance("HKDF-SHA256");
AlgorithmParameterSpec params = HKDFParameterSpec.ofExtract()
.addIKM("my-secret-key".getBytes(UTF_8))
.addSalt("unique-salt".getBytes(UTF_8))
.thenExpand("app-context".getBytes(UTF_8), 32);
SecretKey key = kdf.deriveKey("AES", params);
Ne Yapmalı?
- Yeni projeler: Java 25’i varsayılan alın. Virtual threads + Scoped Values + Structured Concurrency ile temiz temel kurun.
- Mevcut projeler: Önce staging’de deneyin; Compact Object Headers ve Generational Shenandoah’ı metriklerle açın.
- Hız kritikse: AOT cache profillerini üretim başlangıcında kullanın. İzleme için JFR CPU time + cooperative sampling’i etkin tutun.
Özet: Daha az seremoni, daha sade concurrency, kutudan çıkan daha iyi performans. LTS olduğu için geçişin bedeli, uzun vadede fazlasıyla geri dönüyor.