The Fourth Digit, a Twelve-Year Silence, and a Plan for When the Dinosaurs Get Out - JVM Weekly vol. 188

What happens to a release train when something more urgent needs the track, what twelve years of indecision look like on a status page, and what a maintainer does when good faith runs out.

Thanks for reading JVM Weekly! Subscribe for free to receive new posts and support my work.

1. The fourth digit

On Tuesday, Java got a batch of patches outside the quarterly schedule. Not because anything broke. The OpenJDK update trees put out 11.0.32.1 and 26.0.2.1. And the reason why is interesting story by itself.

A quick refresher on the mechanism, because I suspect very few people carry this around in their heads. JEP 322: Time-Based Release Versioning, which rolled in alongside Java 10, fixed the scheme as $FEATURE.$INTERIM.$UPDATE.$PATCH.

$FEATURE is the number you actually use: 21, 25, 26. $INTERIM is permanently zero, because the interim releases it was designed for never happened (a small monument to 2018 optimism, sitting in every java -version and bothering nobody). $UPDATE is the number of the quarterly patch release. And the fourth part, $PATCH, Oracle’s documentation describes as reserved for an emergency release fixing a critical bug. Hence 11.0.9.1, the 17.0.8.1 above, and a handful of similar numbers, which for years signalled one thing only: somewhere, 💩 hit afun.

As of Tuesday it isn’t the emergency slot anymore.

We’ve known the reason since April, though back then it covered Oracle’s whole product line and none of us paid much attention. The company introduced CSPUs, Critical Security Patch Updates: patch releases in between the quarterly CPUs (Critical Patch Updates). The announcement on Oracle’s blog, signed by Donald Smith VP of Product Management, doesn’t mince words: the newest generation of AI is changing how vulnerabilities get found and exploited, on both sides of the fence, and a quarter is simply too long at that pace. The number behind it lands. July’s CPU carried 1,448 patches, the largest in the programme’s history, against 481 in April and 309 a year ago. The line goes steeply up and there’s no sensible way to argue with it.

That’s worth unpacking, because the sentence about AI hides the interesting part, and it isn’t the finding. A quarterly release is a single disclosure event: the moment it ships the patched binaries are public, and the patch is a map to the bug it fixes. You take the before and the after, work out what changed, reconstruct the vulnerability. It’s called patch diffing and it’s as old as patching.

Quarterly was safe only because that work was slow: WannaCry landed 59 days after the MS17-010 patch, and weeks like those were the whole reason a staged rollout across a fleet made sense. In April the Marimo project published an advisory for a bug allowing remote code execution without logging in, with no proof-of-concept attached, just the write-up, and Sysdig recorded the first exploitation in the wild nine hours and forty-one minutes later.

Now hold that against a batch of 1,448 patches, because batch size is the size of the map handed over in one go: quarterly doesn’t mean “we patch four times a year”, it means “four times a year we publish, all at once, everything we fixed in the previous three months”. Shipping more often gets fixes out sooner, which is the obvious gain. The one that matters more is that each release hands over a smaller map.

Java joined in July and the first release landed on Tuesday. There’s no CSPU in September, so October’s CPU will be fatter than usual, and next year brings considerably more of them. If your runbook says “we patch Java quarterly”, that’s now wrong rather than simplified. Same goes for the slide you last showed an auditor.

For the OpenJDK update trees this means a serious rebuild of process. The model Rob McKenna laid out on the jdk-updates-dev list has the CSPU branch forking from the prior GA tag, taking only previously embargoed changes on publication day, and accepting nothing public in between beyond procedural commits. So for a few days each month the update tree has a private branch nobody outside can open a pull request against.

Andrew Hughes confirmed the other trains, 8u through 25u, will treat CSPUs the way they already treat interim releases. What that means for distributors (Temurin, Corretto, Liberica, Zulu) is in a good Frank Delporte piece on what CSPUs do to your release pipeline.

Mark Reinhold, Java’s chief architect, moved JDK 27’s first release candidate. It was due on 6 August. It lands today, 20 August, so it doesn’t collide with Tuesday’s patch release. GA stays on 15 September, so something had to give. What gave was the feedback window: down from five weeks and four days to three weeks and four days. Reinhold called that an increase in risk himself, at least theoretically, and immediately supplied the argument for why he finds it acceptable: since the move to a six-month cadence in JDK 10, a second RC build has been needed for fewer than half of all releases, and not one of the bugs that forced those builds was reported by an end user.

The argument is sound and Reinhold is probably right (he usually is). But let’s note what just happened: the six-month release train, treated since 2017 as the immovable point in Java’s calendar, bent under the patch schedule. Quietly, in a single paragraph on a mailing list, with no JEP and no announcement. For eight years everything arranged itself around that train. This time the train arranged itself around something else.

2. Twelve years waiting on JSON

Since we’re on the subject of what the JDK delivers and how fast, let’s stay here a moment longer, because a quiet execution took place in the background.

JEP 540: Simple JSON API (Incubator) is now targeted for JDK 28. In the process, JEP 198: Light-Weight JSON API was formally closed and withdrawn. Check the date on that second one: Mike Duigou filed it in June 2014. Java 8 shipped the same year, so if you want a reference point, some of you still have one in production.

For twelve years the platform couldn’t decide whether parsing JSON was any of its business, and in that time Jackson and Gson became part of Java in every sense except the formal one.

I know, I know, JSON in 2026 isn’t a subject that sets the imagination alight (I’ve probably just lost a chunk of you to section three, where there’s an actual fight). But this particular cycle is more interesting than it looks, because Java repeats it regularly. HttpClient only reached the JDK in version 11, after years in which every project dragged in Apache HttpClient or OkHttp. The PEM API turned up in version 25. Each time the question is the same and each time nobody answers it directly: what should the platform guarantee itself, and what does it leave to libraries that in practice nobody maintains as a day job. “We leave it to the libraries” is a perfectly defensible answer, but then it’d be good to know who maintains those libraries. We’ll come back to that shortly, I promise.

The more interesting thing is what happened on the day of the announcement. In the Hacker News thread, a commenter going by dfabulich picked up the JEP’s own goal, processing JSON “with low ceremony”, and pointed out that what the examples actually show is a lot of ceremony. Specifically: whether you really can’t build a JsonArray out of plain strings, booleans and numbers without explicitly wrapping every value in a JsonValue, and why a List has to be converted to a JsonArray before it can go into a JsonObject at all. For anybody who has ever written objectMapper.writeValueAsString(map), that’s the difference between one line and fifteen.

The complaint stings all the more because the JEP justifies its own existence with a sentence about how the Python or Go code for these tasks is simple and the Java code should be equally simple. It’s hard to hand your critics a better stick to beat you with (a little self-respect, dear spec authors).

In fairness though: this is still an incubator, which is exactly the stage where remarks like that make sense and can change something. Incubating APIs go through deep rewrites all the time, and the Vector API has been sitting there since JDK 16 and is still moving, so there’s time to spare. Let’s not declare failure on launch day.

Just worth noting that after twelve years of waiting, the community’s first reaction wasn’t “at last” but “seriously, that’s what it looks like?”.

3. The lysine contingency and other licensing shuffles

I promised to come back to the question of who maintains the things the JDK doesn’t deliver. The answer from the last two months: increasingly, somebody who has just started charging for it. But before we get there, the best story of the summer.

On 17 June, Jake Wharton announced that Retrofit, OkHttp and Okio were moving to a new GitHub organisation and, together with SQL Delight, joining the Commonhaus Foundation. For the record, because the scale is easy to miss: those three repositories carry just over 100,000 GitHub stars between them, OkHttp is the networking engine underneath a very large share of what runs on Android, and Retrofit is probably the thing you last called a REST API through.

The official reasoning is diplomatic and talks about projects that long ago outgrew the stewardship of a single company. A few paragraphs down, Wharton stops being diplomatic. He writes that he and Jesse Wilson left Square on the same day last November, assuming the company would keep running these projects in good faith. And that it didn’t.

The name of the new organisation, lysine.dev, is my favourite detail in the whole affair. The lysine contingency is the fallback plan from Jurassic Park for when the dinosaurs get off the island, and Wharton writes plainly that their version is a plan to limit the damage their old company can do. Normally a change of repository ownership comes with a note about a “new chapter” and an “exciting direction”. Here we got a metaphor from a film about everything getting loose and eating people. Respect.

Five days later, Commonhaus announced the Open Source Sustainability Initiative, with HeroDevs as a founding member. To start with, the programme covers commercial support for end-of-life versions of Hibernate, Jackson and Quarkus: security patches and CVE remediation for companies that haven’t managed to upgrade in time. The reasoning in the HeroDevs announcement comes from Rob Nalen, the company’s COO, and after section one it’ll sound familiar: pressure on maintainers is growing because AI is accelerating software development, dependency sprawl and vulnerability discovery all at once (that is, everything at once except the number of maintainers).

The third example will hit more readers of this piece directly than the other two, so pay attention. Maven Central is introducing publishing limits, and the thresholds sit at the point where the top ten per cent of publishers begins. They look like this: 1,167 files, 78 megabytes and seven releases a month.

Seven releases a month. That’s enough to put you in the top ten per cent of everyone publishing to Maven Central. Go and count how many times your monorepo cut a release this month, then observe a moment of silence.

The data behind this is in Sonatype’s documentation and the concentration is extreme: over the last 90 days, ten per cent of namespaces accounted for more than 88 per cent of all files published. The file counter includes signatures, checksums, POMs, source jars and javadoc, so a twenty-module project eats through them faster than intuition suggests. The sentence Sonatype closes with is exactly the same claim as OSSI’s, only about infrastructure instead of code: commercial companies whose business rests on open source infrastructure have an obligation to help support it.

And here’s the punchline, which I didn’t have to reach far for, because Sonatype laid it out themselves. One of the pieces the company uses to justify the change is titled “Maven Central and the Tragedy of the Commons”.

That’s precisely the phrase Jonas Bonér used in 2022 to explain moving Akka from Apache 2.0 to the Business Source License. And we will use it to close the story.

Quick background for anyone who slept through this one. Akka is a library for building concurrent and distributed systems on the JVM, built on the actor model, for years the default choice in the Scala world and the foundation under Play Framework among others. The Business Source License is a source-available licence: you can still read the code, but running it in production costs money once your company clears 25 million dollars in revenue, and the price started at 1,995 dollars per core per year. The community forked the last Apache 2.0 version, and that fork is Apache Pekko, today a project of the Apache Software Foundation.

You remember how we took it at the time. The clause returning the code to Apache 2.0 after 36 months got written off as a fig leaf, because nobody in their right mind builds on three-year-old dependencies (good moment for a quick inventory of your pom.xml).

That was right about the dependencies and wrong about who the clause was for. It was never going to help users, who would indeed rather not run 2022 code in 2025. It helps a fork. Apache Pekko doesn’t ship Akka 2.7 to anyone. It takes what 2.7 added and merges it into a codebase that is current, and its README says so today. So the licence change created a competitor, and then handed that competitor everything Lightbend builds, three years late, forever. Akka can’t switch that off without deleting the clause that made BSL look reasonable in the first place. Lightbend put that sentence in to show the restriction was temporary. It was. It is also the most expensive sentence in the licence.

And Akka the company, after rebranding from Lightbend, runs a technical support page for Pekko that advertises the same clause as a selling point.

Four years ago we were all certain it meant nothing. Worth going back to that argument with what we know now, because both sides came out of it less clever than they thought at the time (myself included, so this isn’t a dig at anyone in particular).

Four years ago we were all certain it meant nothing. Worth going back to that argument with what we know now, because both sides came out of it less clever than they thought at the time (myself included, so this isn’t a dig at anyone in particular).

Oh, time flies.

PS: Sections two and three interlock more tightly than I planned, and I only noticed while assembling the issue. I decided that was an argument for, not against.

PS2: If you publish anything to Maven Central, the Usage Center in the portal will show you where you stand against the thresholds. Far better to check that now, over coffee, than to find out from a red pipeline on a Friday afternoon.

Thanks for reading JVM Weekly! Subscribe for free to receive new posts and support my work.

添加评论
点赞收藏
点踩分享查看原文
评论
?
参与讨论