2 + 2 = 5 – and how a patch update makes you admin
Hello John Doe,
Imagine you start an application, and suddenly 2 + 2 equals 5. Three lines are all it takes:
Field value = Integer.class.getDeclaredField("value");value.setAccessible(true);value.set(4, 5);
Integer.value is private and final – and yet set() overwrites it. Because Java caches the Integer 4, every boxed calculation with the result 4 now returns 5.
A party trick. It becomes dangerous when the target isn’t Integer.value but the roles of the user who just logged in.
One patch update, and alice is admin
In my new article, I show a small Spring Boot application with a protected admin area. alice has no special role and can’t get into the admin area when she calls /admin (HTTP 403).
Then the application updates an inconspicuous request-timing library from 1.0 to 1.0.1 – a patch release that Dependabot waves through without asking. The new version uses deep reflection to overwrite the final field authorities in alice’s authentication token. Result: alice has admin rights and gets into the admin area. Not a single line of application code changed, no command-line option set.
Up to Java 25, this leaves no trace. For classes on the classpath, final is merely a statement of intent.
What JEP 500 does about it
Since Java 26, the JVM warns as soon as code overwrites a final field via reflection – naming the field, the class that wrote it, and the full path of the JAR. With --illegal-final-field-mutation=deny, you can block such writes today; a future Java version will make that the default.
What you can do now:
- Find affected code: with
--illegal-final-field-mutation=debugor the Flight Recorder eventjdk.FinalFieldMutation. - Make security-relevant state
final– roles, keys, limits, flags. Whatever is final, JEP 500 protects. Records are safe anyway: their fields can’t be overwritten via reflection at all.
👉 JEP 500: Final Means Final – Deep Reflection in Java 26
Today: the first paid update for Oracle JDK 21
Today, the quarterly Java updates come out, including Java 27.0.1. For Oracle JDK 21, this one is a turning point: the free NFTC license only covers updates up to and including September 2026. Today’s update ships under the OTN license, which doesn’t allow free production use.
If you run Oracle’s Java 21 binaries, you now pay for new security patches – or you switch to an OpenJDK distribution such as Eclipse Temurin or Amazon Corretto. For an overview of which distribution fits which use case, see whichjdk.com.
Java 28 is taking shape
Ten JEPs are now targeted to Java 28. Three of them you’ll notice in your own code:
- Value Objects (JEP 401, preview) – objects without identity, compared only by their values. In return, the JVM may store them more compactly: less memory, less work for the garbage collector. That’s the topic of the next issue.
- Structured Concurrency goes final (JEP 543) – concurrent subtasks that start together, end together, and pass on failures cleanly; from Java 28 on without
--enable-preview. 👉 Structured Concurrency with StructuredTaskScope - Ahead-of-Time Code Compilation (JEP 544) – your application reaches full speed sooner after startup, without changing a line of code: the AOT cache will also contain compiled code from a training run.
Also coming, among others: a JSON API as an incubator (JEP 540), PEM encodings as a final feature (JEP 542), and two JEPs that make ZGC start faster and size the heap on its own (JEP 545 and 546). Feature freeze is expected on December 3.
Have you already spotted the final-field warning in one of your logs? Just reply to this email – I read every answer.
Until next time,
Happy Coding!
Sven
P.S.: Know someone who would benefit from these Java news? Feel free to forward this email.
Java training for your team?
I show teams what modern Java versions bring – from Records, Virtual Threads and Pattern Matching to JVM and GC optimizations. In-house, on site or remote.
If that fits your team: