What's coming in JDK 27... and why OpenJDK just said no to your Copilot - JVM Weekly vol. 171
The schedule is on the table, Valhalla is on the horizon, and OpenJDK says "no" to AI-generated code.
Just a month after JDK 26 shipped, the release machine is already running at full speed. Mark Reinhold has formally proposed the release schedule for JDK 27, early-access builds are already in double digits, and on top of that, the JVM community is buzzing with discussion around OpenJDK’s new policy on generative AI. A lot is happening - let’s break it down.
1. JDK 27: The Calendar and the Only (So Far) Official JEP
Mark Reinhold, Chief Architect of the Java Platform Group at Oracle, formally proposed the release schedule for JDK 27: Rampdown Phase One (fork from main line) is set for June 4, 2026, with GA - as tradition dictates - in September. The review period for this schedule concluded on April 13, so we can effectively treat these dates as locked in. Build 17 early-access is already publicly available.
This means JDK developers have less than two months to target additional JEPs. And right now, we formally have one single officially targeted JEP: JEP 527: Post-Quantum Hybrid Key Exchange for TLS 1.3. It enhances TLS 1.3 with a hybrid key exchange mechanism resistant to quantum computing attacks, building on JEP 496 (Quantum-Resistant ML-KEM) delivered in JDK 24. The topic of “quantum-ready” cryptography is slowly shifting from the “science fiction” category to “infrastructure we should have had yesterday” - especially if you operate in regulated sectors. The first JEP targeted to the twenty-seventh version of Java is about security - and that says something about priorities.
But “one official JEP” doesn’t mean it’s going to be boring. Based on JEPs in Candidate status and active drafts, we can point with reasonable confidence to what else should land in JDK 27 - and this is where things get interesting.
2. Valhalla Finally Knocks on the Door: JEP 401 Value Classes
If I had to bet on which JEP will be the most important one in JDK 27, I’d go all in on JEP 401: Value Classes and Objects (Preview). Project Valhalla, after years of conceptual work and prototyping, has a real chance of debuting in preview in the mainline JDK.
What’s the deal? Value classes are classes whose instances lack object identity. == compares them by field values, not by reference. Sounds simple, but the implications are massive - the JVM can optimize their memory layout through heap flattening (objects in arrays stored flat, without indirection) and scalarization (avoiding allocation in JIT-compiled code). And the code change? Laughably small:
// One keyword changes everything
public value class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
// Works with records too:
public value record Color(byte r, byte g, byte b) {}The value keyword before class or record - and instances lose their object identity. All fields are implicitly final, the class is implicitly final, and the JVM gains optimization freedom. Inside the early-access build, JDK classes like Integer and LocalDate become value classes, which yields rather spectacular results in JShell:
jshell> Objects.hasIdentity(Integer.valueOf(123))
$1 ==> false
jshell> Objects.hasIdentity("abc")
$2 ==> true
jshell> LocalDate d1 = LocalDate.of(2025, 1, 1)
jshell> LocalDate d3 = d1.plusYears(1).minusYears(1)
jshell> d1 == d3
$8 ==> true // two different "instances", same day — == returns true!After years of writing about Valhalla, seeing this in JShell genuinely hits different.
The Valhalla team published the latest early-access build in March 2026 and is actively encouraging developers to test on real-world workloads. Worth noting: Nicolai Parlog on Inside Java Newscast #100 did an excellent job explaining value class semantics - the syntactic change is laughably small (the contextual keyword value before class or record), but everything else follows from it. Highly recommended.
And as a bonus - if JEP 401 enters preview, it will finally unblock the Vector API, which has been incubating since JDK 16 (currently in its eleventh round...) waiting precisely for Valhalla to properly express its types. As Java Code Geeks analyzed, JDK 27 or JDK 28 is the most likely window for that transition. Twelve to fourteen total incubations - sounds absurd, but the incubation model is working exactly as designed. Shipping a structurally wrong API permanently would have been the real mistake.
3. The Rest of the Candidates: Lazy Constants, Pattern Matching, and ZGC
Beyond Valhalla, there are several more JEPs that should land in JDK 27.
JEP 531: Lazy Constants (Third Preview) - the third preview round of what used to be called Stable Values, and before that, Computed Constants. In this iteration, changes include removing the isInitialized() and orElse() methods from the LazyConstant interface (as they didn’t align with the feature’s design goals) and a new ofLazy() factory method for creating stable collections - List, Set, and Map with pre-defined, lazily initialized elements. The new addition in the third preview - Set.ofLazy() - looks like this in practice:
class Application {
enum Option { VERBOSE, DRY_RUN, STRICT }
// Each Set element is initialized lazily, only on first access
static final Set<Option> OPTIONS =
Set.ofLazy(EnumSet.allOf(Option.class), Application::isEnabled);
private static boolean isEnabled(Option option) {
// Parse CLI, read config, query database... expensive operations
}
public static void process() {
if (OPTIONS.contains(Option.DRY_RUN)) {
return; // Only this option gets initialized
}
// ...
}
}
// And Map.ofLazy() enables even more expressive patterns:
static final Map<String, OrderController> ORDERS =
Map.ofLazy(
Set.of("Customers", "Internal", "Testing"),
_ -> new OrderController()
);The key idea: every element in the collection sits in its own LazyConstant and initializes only on first access. Thread-safe by construction, and the JVM can constant-fold after initialization. The feature consistently matures with each iteration and is getting closer to finalization.
JEP 532: Primitive Types in Patterns, instanceof, and switch (Fifth Preview) — the fifth (!) preview round, this time with no changes from the fourth in JDK 26. It has just advanced to Candidate status. It extends pattern matching with primitive types in all pattern contexts, adds tighter dominance checks in switch, and refines the definition of unconditional exactness. The fact that there are no changes paradoxically suggests finalization is close — the feature has matured to the point where there’s nothing left to fix. Been with us since JDK 23 - if you’re counting preview rounds on your fingers, you’ve run out of one hand.
JEP Draft 8329758: Faster Startup and Warmup with ZGC - still a draft (so it might not make it into JDK 27), but the direction is clear: the Z Garbage Collector should more efficiently allocate memory at application startup, minimizing the initial heap and OS overhead. Together with JEP 516 (AOT Object Caching with Any GC) from JDK 26, Project Leyden is steadily building the foundation for faster Java startup. The patient will be rewarded - though with Leyden, patience is measured in releases.
4. OpenJDK Bans AI-Generated Code: “Use It, But Don’t Commit It”
And now for the topic that electrified not just the JVM world.
OpenJDK published an Interim Policy on Generative AI that unambiguously prohibits contributing content generated by LLMs, diffusion models, or other deep-learning systems. The policy covers not just source code, but also text and images in Git repositories, GitHub pull requests, email messages, wiki pages, and JBS issues.
Interestingly - this isn’t a blanket AI ban. The policy explicitly encourages private use of generative AI tools to comprehend, debug, and review existing code, as well as for research related to OpenJDK Projects. The restriction applies solely to one step: creating and submitting content generated by those tools. Even sharing output with a colleague is fine — as long as you add a comment identifying it as AI-generated.
The rationale is three-layered, and it’s worth understanding because it describes the realities of large open source projects well.
First - reviewer burden. Generative AI makes it easy to create large quantities of “plausible-looking” code with “plausible-looking” tests that is nonetheless incorrect or poorly designed. As someone on Hacker News aptly summarized: the number and size of AI-assisted PRs have reached a tipping point, and “filtering out even the obvious ones is a drain” on the already limited time of human reviewers.
Second - safety and security. The JDK sits at the foundation of mission-critical systems worldwide. Plausible-looking but incorrect code poses a direct risk to those systems. OpenJDK can’t afford to be a testing ground.
Third - intellectual property. The Oracle Contributor Agreement (OCA) requires that a contributor own the IP rights to each contribution. Generative tools trained on copyrighted content create legal uncertainty here, which is the subject of active litigation.
The enforcement mechanism? Skara, the tool responsible for pull request workflow in OpenJDK, has been extended with a checkbox that contributors must check when creating a PR, affirming compliance with the policy. Of course, this is a trust-based mechanism. But the policy also lists some rather amusing “tell-tale clues” for spotting AI-generated content: an overly chatty, verbose commenting style, heavily structured responses with multiple headings, unnecessary code comments, gratuitously defensive programming, and... emoji characters. Official OpenJDK position.
Other clues include highly structured comments with multiple headings, unnecessary comments in code, gratuitously defensive programming, and the use of emoji characters. (...) In general, if something in a pull request seems uncannily cheerful or meticulous then you could be looking at AI-generated content.
What’s fascinating - not everyone in the Oracle ecosystem agrees. GraalVM has taken a diametrically opposite stance. Their policy on coding assistants explicitly states that contributors may use AI when preparing contributions, and that responsible use of such tools should increase development velocity and improve quality - e.g., by helping produce clearer documentation, broader test coverage, and more complete supporting changes. The document is inspired by the Linux kernel’s policy, which follows the same path. GraalVM’s key condition: the human submitting a change remains responsible for the entire contribution, must understand and be able to defend every piece of code, and if they can’t -the change gets rejected. But it’s accountability for quality, not a ban on the tool.
So we have a situation where two projects under Oracle’s umbrella - OpenJDK and GraalVM - occupy diametrically opposite positions. OpenJDK says “don’t commit AI-generated code in any form,” GraalVM says “use it, but take full responsibility.” This isn’t a contradiction - it reflects different contexts. OpenJDK is the platform foundation on which mission-critical systems globally depend, with a rigorous OCA process and a vast base of external contributors with varying levels of experience. GraalVM is a smaller project with a more specialized community, where maintainers know their contributors better. But the contrast is striking.
Looking more broadly, OpenJDK isn’t alone in its approach - QEMU adopted a similar ban, r/programming banned AI-generated content, Debian debated and... decided not to decide (classic Debian). And on the other side - GraalVM and the Linux kernel bet on individual responsibility instead of a blanket ban. I see a fascinating paradox here: AI tools are changing how we write code every day, yet the open source community doesn’t have a unified answer, even within the same ecosystem. This dissonance will only grow - and it’s a topic we’ll be discussing for a long time to come.
PS: If you want to discuss this paradox in person - join us at NY Tech Week, June 2 in New York, where Tomasz Lelek and I will be talking about Vibe Engineering and how AI is (or isn’t) changing the way we work with code.
PS2: In the meantime - download that Valhalla EA build and test it on your workloads. Seriously. After all these years of waiting, feedback from real users is the best thing we can do for Java.







