Java 27 shipped in September 2026. It's a non-LTS release, so most production teams will skip it and stay on Java 25 LTS, but a few of the defaults it ships are worth knowing about even if you never install it. G1 is now the only default GC (JEP 523). Small/constrained JVMs used to silently get Serial GC instead Object headers shrink from 96 bits to 64 bits, on by default (JEP 534). Real measured savings, not a flat percentage (details below) TLS 1.3 gets quantum-resistant key exchange, on by default (JEP 527). Zero code changes for most apps Pattern matching finally works on primitives (JEP 532, 5th preview). switch (int) with guards, no boxing Structured Concurrency, Lazy Constants, Vector API all get another preview/incubator round (JEP 533, 531, 537) No huge syntax additions this cycle. It's mostly two years of JDK 25 experiments getting switched on by default. Here's what that means for code you actually run. G1 everywhere (JEP 523) Before 27, GC selection depended on your machine's CPU count and memory at JVM startup. Constrained environments, think a 1-CPU container, could end up on Serial GC without anyone choosing it: $ java -XX:ActiveProcessorCount=1 -Xmx256m -Xlog:gc -version [0.006s][info][gc] Using Serial That's a real capture, not hypothetical. I ran it. On Java 27, the same command reports Using G1, unconditionally. If you were relying on Serial's lower overhead for a sidecar, -XX:+UseSerialGC still works; it just stops being a default you get without asking. Compact Object Headers, and the part nobody explains (JEP 534) The pitch: header size drops from 96 bits (12 bytes) to 64 bits (8 bytes), and the JEP cites 10 to 20% less heap for typical workloads. True, but incomplete. HotSpot rounds every object up to an 8-byte boundary, so the saving only shows up when the smaller header crosses that boundary. I benchmarked five tiny classes (0 to 4 int fields, 10M instances each) with MemoryMXBean, once per header mode: Fields Standard header Compact header Saved 0 ints 16.00 B 8.00 B -50% 1 int 16.01 B 16.00 B 0% 2 ints 24.00 B 16.00 B -33% 3 ints 24.00 B 24.00 B 0% 4 ints 32.00 B 24.00 B -25% A clean sawtooth. The win shows up exactly where the header saving pushes an object across a rounding boundary the standard header didn't, and vanishes where both land on the same boundary. If you're allocating millions of small objects, re-run this against your own classes before assuming "10 to 20%" applies to you. javac -d out src/HeaderSizeBench.java java -Xmx4g -cp out HeaderSizeBench # standard headers java -Xmx4g -XX:+UseCompactObjectHeaders -cp out HeaderSizeBench # compact headers (Finalized since JEP 519 in JDK 25, no experimental flag needed anymore.) Post-quantum TLS, and proving it's not in 25 yet (JEP 527) TLS 1.3 now negotiates a hybrid key exchange, classical ECDHE plus NIST-standardized ML-KEM, automatically, whenever both peers support it. The motivation is "harvest now, decrypt later": someone can record your encrypted traffic today and decrypt it once quantum hardware exists, so the defense has to ship before the threat is fully real. I didn't just take the JEP's word for it. Real handshake, real server: attempt("default groups (control)", factory, host, null); attempt("X25519MLKEM768 only", factory, host, new String[]{"X25519MLKEM768"}); attempt("X25519MLKEM768 + x25519 + secp256r1 (fallback)", factory, host, new String[]{"X25519MLKEM768", "x25519", "secp256r1"}); [default groups (control) ] SUCCEEDED -- TLSv1.3, TLS_AES_256_GCM_SHA384 [X25519MLKEM768 only ] FAILED -- SSLHandshakeException: (handshake_failure) [X25519MLKEM768 + x25519 + secp256r1 (fallback)] SUCCEEDED -- TLSv1.3, TLS_AES_256_GCM_SHA384 That's JDK 25. The hybrid group isn't implemented yet, so asking for it alone fails outright. Asking for it with a classical fallback succeeds and just negotiates down. That's the whole migration story: list a classical group alongside the PQC one until you've confirmed both ends of a connection support it. Pattern matching on primitives (JEP 532, 5th preview) The one actual language feature this cycle. switch and instanceof can match primitive types directly now, guards included, no boxing: int score = 82; switch (score) { case int s when s >= 90 -> System.out.println("excellent"); case int s when s >= 75 -> System.out.println("good"); default -> System.out.println("needs work"); } Still preview (--enable-preview required), and it's been through five rounds of feedback already, so don't treat the exact syntax as locked in. Everything else, briefly Structured Concurrency, 7th preview (JEP 533): this round throws ExecutionException instead of a custom type, and onTimeout() is renamed timeout(). Lazy Constants, 3rd preview (JEP 531): adds Set.ofLazy(). Vector API, 12th incubator (JEP 537): API unchanged this cycle (still waiting on Valhalla), but I ran a real scalar-vs-vector dot-product benchmark on it: about 2.0x measured speedup with 512-bit AVX-512 vectors. Not 16x, because the kernel is memory-bandwidth-bound at that array size, not compute-bound. Worth understanding before you reach for jdk.incubator.vector expecting a free 16x. Should you upgrade? If you're on Java 21 or 25 LTS in production, there's no reason to move yet. Track these features for your next LTS jump. If you're on a personal project or want to try quantum-resistant TLS early, go for it, just don't ship --enable-preview code to production. I wrote all of this up with the full release timeline, glossary, and a longer walkthrough as a free PDF, grab it here, no signup wall. If you find it useful, a review helps other people find it. I've also got real, benchmarked deep-dives on the Vector API and Compact Object Headers numbers above with the full code and methodology, at mellaithy.gumroad.com. Check out the key changes in Java 27 and what they mean for Java developers. Happy to answer questions on any of this in the comments, especially if you've run these benchmarks on different hardware and gotten different numbers. I'd like to compare.