Skip to content

Build1 publisher3 min readPublished

Java 27 makes G1 the collector on the 1-CPU container that used to get Serial

The non-LTS release is mostly two years of JDK 25 experiments switched on by default, and the flipped defaults change memory and handshake behaviour in small containers rather than adding syntax anyone will write.

The Engineer · Build desk

Illustration accompanying Java 27 makes G1 the collector on the 1-CPU container that used to get Serial

What happened

  • Java 27 arrived in September 2026 as a non-LTS release, and the author of the walkthrough expects most production teams to skip it and stay on Java 25 LTS.
  • JEP 523 makes G1 the only default collector, replacing a startup heuristic that could put a small or constrained JVM on Serial GC without anyone choosing it.
  • Compact 64-bit object headers, down from 96 bits, are on by default, and the JEP cites 10 to 20 percent less heap for typical workloads.
  • JEP 527 has TLS 1.3 negotiate classical ECDHE plus NIST-standardized ML-KEM automatically whenever both peers support it, with no code changes for most applications.
  • Primitive pattern matching in switch and instanceof is the only language feature this cycle, still behind --enable-preview at its fifth preview round.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

  • decision A sidecar that was quietly living off Serial's lower overhead now needs -XX:+UseSerialGC written into its launch config by a named owner, because the flag survives the release and the free default does not.
  • cost A heap budget drawn from the JEP's headline percentage is a bet on someone else's object graph, and the team that pays for a wrong bet is whoever set the container memory limit.
  • precedent Pinning the PQC group beside a classical one becomes the expected posture for anyone who configures named groups at all, since a hybrid default that requires both peers cannot be verified from one side.

HotSpot pads every object up to an 8-byte boundary, and that one rule predicts the shape of the header result before you run anything [7]. The header drops from 12 bytes to 8 [5]. Taking an int as four bytes: a class with no fields occupies 16 bytes with standard headers and 8 with compact ones; add one int and both layouts land on 16; two ints gives 24 against 16; three ints ties again at 24; four ints gives 32 against 24 [1]. The saving per instance is therefore either exactly 8 bytes or exactly nothing, which at the 10 million instances allocated per class is 80 MB or zero [2]. The author's measured sawtooth matches that pattern [8]. MemoryMXBean is a coarse instrument for this, though a swing that size survives coarse instruments.

As percentages of the standard layout, the three winning cases are 50, 33 and 25 percent and the two losing cases are zero [3]. None of the five sits in the 10 to 20 percent band the JEP cites [6]. For that band to describe your heap, your live set has to be dominated by classes whose fields put the fat-header layout just above a rounding boundary and the slim-header layout just below it. That is a fact about your field declarations, not about the release.

The handshake evidence is worth reading closely rather than summarising. Against a real server from JDK 25, the control attempt with default groups succeeded on TLS 1.3 with TLS_AES_256_GCM_SHA384, the attempt requesting X25519MLKEM768 alone failed with an SSLHandshakeException, and the attempt listing X25519MLKEM768 with x25519 and secp256r1 succeeded [12]. The author attributes the failure to the hybrid group not being implemented yet [12]. The excerpt does not name the host, so the capture does not separate a client that cannot offer the group from a server that will not accept it. Either way the connection settled on a classical exchange, and because the Java 27 default only fires when both peers support the hybrid [10], harvest-now-decrypt-later coverage is a property of what is deployed at both ends [11].

The GC capture proves that selection changed, not that the change is free. Before 27, a JVM started with ActiveProcessorCount=1 and a 256 MB heap logged "Using Serial"; on 27 the same command reports G1 unconditionally [3]. What no measurement here reports is G1's own footprint and pause behaviour inside that 256 MB, which is the number you would want before deciding whether the old heuristic was doing your sidecar a favour.

The header question is the one that can be answered before you upgrade. JEP 519 finalized compact headers in JDK 25 and dropped the experimental flag [9], so running your own classes under -XX:+UseCompactObjectHeaders is a measurement available on the LTS you are already staying on [1]. The collector switch and the hybrid group only report their numbers on 27.

What to watch

  • Whether a named server can be shown to offer X25519MLKEM768, which would make the failed JDK 25 handshake a client-side gap rather than an ecosystem one.
  • Whether teams re-running the header benchmark on their own class mixes report anything near the JEP's percentage, or the 0-or-8-bytes sawtooth.
  • Whether primitive pattern matching exits preview with the current switch (int) syntax after a fifth round of feedback.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories