Skip to content

Support JDK 27 (JDK-8372948, JDK-8268850) - #1786

Open
slachiewicz wants to merge 3 commits into
palantir:developfrom
lakewire:jdk27-end-positions
Open

slachiewicz wants to merge 3 commits into
palantir:developfrom
lakewire:jdk27-end-positions

Conversation

@slachiewicz

@slachiewicz slachiewicz commented Sep 15, 2026 •

Copy link
Copy Markdown

Before this PR

JDK-8372948 (JDK 27) removed EndPosTable and JCCompilationUnit.endPositions, so Trees.getEndPosition, StringWrapper and RemoveUnusedImports fail with NoSuchFieldError on JDK 27. The same change re-ordered the four-argument ParserFactory.newParser, so Formatter was passing parseModuleInfo=true on JDK 27 without noticing. Fixes #1785.

JDK-8268850 (also JDK 27) gives var declarations a VarTypeTree type instead of null, so the visitors scanned it to nothing and every var failed with expected token: 'var'. Fixes #1799.

After this PR

==COMMIT_MSG==
Support JDK 27 (JDK-8372948, JDK-8268850)

Trees now looks up the end-position API once through a method handle: JCTree.getEndPosition() on JDKs without EndPosTable, and getEndPosition(unit.endPositions) via a VarHandle on older ones. All three call sites go through it, and Trees.newParser passes the parser flags in the order each JDK generation expects. Same approach as google/google-java-format#1328.

var declarations, for-each variables, lambda parameters and record patterns check for var before the declared type, as google/google-java-format#1342 does. The native image registers EndPosTable, JCTree.getEndPosition(EndPosTable) and JCCompilationUnit.endPositions, which the handles reach reflectively (google/google-java-format@ff157e3e46).
==COMMIT_MSG==

Verified: ./gradlew :palantir-java-format:check → 1405 tests pass; on JDK 27 the built CLI formats the repo's 383 test inputs identically to JDK 21, including var in locals, for-each loops, lambdas and record patterns. The native image was not built locally.

Possible downsides?

The handle is resolved from class presence, not from the runtime version number, so an early-access build that has one half of JDK-8372948 but not the other would fail at class init instead of at the first formatted file. No such build exists in the released tags.

On JDK 27 JCTree.getEndPosition() returns the start position where the old API returned -1 (NOPOS); none of the call sites relies on -1.

This change was created with AI assistance.

@palantirtech

Copy link
Copy Markdown
Member

Thanks for your interest in palantir/palantir-java-format, @slachiewicz! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request.

@changelog-app

changelog-app Bot commented Sep 15, 2026

Copy link
Copy Markdown

Generate changelog in changelog/@unreleased

Type (Select exactly one)

  • Feature (Adding new functionality)
  • Improvement (Improving existing functionality)
  • Fix (Fixing an issue with existing functionality)
  • Break (Creating a new major version by breaking public APIs)
  • Deprecation (Removing functionality in a non-breaking way)
  • Migration (Automatically moving data/functionality to a new system)

Description

Support JDK 27 end positions (JDK-8372948)

Trees now looks up the end-position API once through a method handle: JCTree.getEndPosition() on JDKs without EndPosTable, and getEndPosition(unit.endPositions) via a VarHandle on older ones. All three call sites go through it, and Trees.newParser passes the parser flags in the order each JDK generation expects. Same approach as google/google-java-format#1328.

Check the box to generate changelog(s)

  • Generate changelog entry

@slachiewicz

This comment was marked as resolved.

@talios

talios commented Sep 23, 2026

Copy link
Copy Markdown

Any idea if/when this change will be merged and released? Looking forward to updating our code base to Java 27 and this is the primary blocker.

@talios

talios commented Oct 5, 2026

Copy link
Copy Markdown

What's the current status of this PR? I see the CLA was signed by OP, and the changelog entry was updated, although no checks seem to have picked that up.

@slachiewicz

Copy link
Copy Markdown
Author

@talios The change is ready and rebased on develop, and the CLA is signed. What's left needs a maintainer: start the CircleCI build, which doesn't run for this fork PR, and tick Fix + Generate changelog entry in the changelog-app comment above, which only repo admins can edit. @crogoz @pkoenig10, could one of you take a look?

slachiewicz added a commit to apache/maven that referenced this pull request Oct 12, 2026
JDK 26 is out of support now that 27 is released. Spotless is skipped on
the JDK 27 jobs only: palantir-java-format crashes there until
palantir/palantir-java-format#1786 is released.
@slachiewicz slachiewicz changed the title Support JDK 27 end positions (JDK-8372948) Support JDK 27 (JDK-8372948, JDK-8268850) Oct 12, 2026
@slachiewicz

Copy link
Copy Markdown
Author

Pushed two more commits: var declarations on JDK 27 (JDK-8268850, fixes #1799) and native-image metadata for the end-position handles. With them, the 383 test inputs format identically on JDK 21 and 27. CircleCI still does not start on this PR, although other fork PRs build, and my fork has no CircleCI project or webhook of its own, so I cannot see the cause from here. @crogoz @pkoenig10 could one of you trigger it?

slachiewicz added a commit to apache/maven that referenced this pull request Oct 12, 2026
The profile applies to local builds as well as CI, so the -Dspotless.skip
arguments leave the workflow. Drop it once maven-parent ships a
palantir-java-format that runs on JDK 27 (palantir/palantir-java-format#1786).
slachiewicz added a commit to apache/maven that referenced this pull request Oct 12, 2026
The profile applies to local builds as well as CI, so the -Dspotless.skip
arguments leave the workflow. Drop it once maven-parent ships a
palantir-java-format that runs on JDK 27 (palantir/palantir-java-format#1786).
slachiewicz added a commit to apache/maven that referenced this pull request Oct 12, 2026
JDK 26 is out of support now that 27 is released. Spotless is skipped on
the JDK 27 jobs only: palantir-java-format crashes there until
palantir/palantir-java-format#1786 is released.
slachiewicz added a commit to apache/maven that referenced this pull request Oct 12, 2026
The javadoc report forks a build that runs spotless:check, which crashes on
JDK 27 like the main build (palantir/palantir-java-format#1786).
slachiewicz added a commit to apache/maven that referenced this pull request Oct 12, 2026
The profile applies to local builds as well as CI, so the -Dspotless.skip
arguments leave the workflow. Drop it once maven-parent ships a
palantir-java-format that runs on JDK 27 (palantir/palantir-java-format#1786).
slachiewicz added a commit to apache/maven that referenced this pull request Oct 12, 2026
JDK 26 is out of support now that 27 is released. Spotless is skipped on
the JDK 27 jobs only: palantir-java-format crashes there until
palantir/palantir-java-format#1786 is released.
@slachiewicz slachiewicz reopened this Oct 19, 2026
@slachiewicz

Copy link
Copy Markdown
Author

@crogoz @pkoen CircleCI is green now. Two checks need a maintainer: docs/changelog waits for Fix and Generate changelog entry to be ticked in the changelog-app comment above, which I can't edit, and policy-bot needs an approval.

@fleboulch

Copy link
Copy Markdown

Wow thanks for your work 💪
Do you know if this MR will be merged soon?

@talios

talios commented Oct 26, 2026

Copy link
Copy Markdown

Wow thanks for your work 💪 Do you know if this MR will be merged soon?

We can only hope!

@slachiewicz

Copy link
Copy Markdown
Author

@pkoenig10 @crogoz CI is green and the branch merges cleanly. Two clicks remain, both maintainer-only: tick Fix and Generate changelog entry in the changelog-app comment above, and a policy-bot approval. JDK 27 is GA, so #1785 and #1799 now hit anyone formatting on it.

@christophercolumbusdog

Copy link
Copy Markdown

Could we please get a maintainer to take a look here? With JDK 27 in GA and a fix ready to merge, it's very frustrating that it's still an open issue. I had to turn off Palantir formatting for one of our projects migrating to Helidon 27, and I'd really like to turn it back on ASAP.

@jvissers

Copy link
Copy Markdown

What a coincidence, I'm using Helidon 27 too, and in my maven setup I had to work around this issue by running the formatter with JDK 26. OSS does not owe us anything, I understand that, but it is unfortunate that something like this takes many weeks to get through the red tape.

@talios

talios commented Oct 30, 2026

Copy link
Copy Markdown

it is unfortunate that something like this takes many weeks to get through the red tape.

I'm not even sure it's red tape at this point, but more lack of visibility from those who can click those two remaining checks.

There's just not much communication from the project maintainers. Here's hoping for a merge (and release) soon.

@fleboulch

Copy link
Copy Markdown

Is there some people thinking about quitting palantir for google format?

@peterunold

Copy link
Copy Markdown

Is there some people thinking about quitting palantir for google format?

I've been eying open-java-format.

@talios

talios commented Nov 2, 2026

Copy link
Copy Markdown

I've been eying open-java-format.

Likewise, they pulled, merged, and released the initial patches in this stack but not sure about the rest. Sadly, the guys at spotless don't want to include it as an option which is kind of annoying.

@kwin

kwin commented Nov 3, 2026

Copy link
Copy Markdown

@talios Where is the issue/PR at spotless which asked for integration of open java format?

@talios

talios commented Nov 4, 2026

Copy link
Copy Markdown

@talios Where is the issue/PR at spotless which asked for integration of open java format?

Took me awhile to find it but it's at diffplug/spotless#3084

I wish you good luck with your project, but it's in a very crowded space. Right now, it's not differentiated enough from other similar projects to merit a spot in the table of contents. And with LLMs, I think formatters are less important than ever! My advice would be to work on something else, but if you find a way to be extremely different than the existing entries feel free to reopen.

@andrej-urvantsev

Copy link
Copy Markdown

Any updates on the PR status?..

@jvissers

jvissers commented Nov 9, 2026

Copy link
Copy Markdown

It's probably time to abandon this formatter, seems like there are no maintainers left willing to take PRs seriously.

Open Java Format maybe?
https://x.com/glaforge/status/2119805712956346513?a=DPPUFB51KlxG2Of0tyA&s=19

@talios

talios commented Nov 9, 2026

Copy link
Copy Markdown

@jvissers If we can get Spotless to accept that PR from @glaforge, that would be awesome. Otherwise, I suspect I'll rip Palantir out of my Spotless config and add their own plugin, which is a bit messy but better.

@jvissers

Copy link
Copy Markdown

For the Helidon 27/Java 27 project (small service) - I just migrated to fmt-maven-plugin and open-java-format. I actually need something that works for Java 27, and clearly spotless/palantir isn't working.

@talios

talios commented Nov 10, 2026

Copy link
Copy Markdown

I actually need something that works for Java 27, and clearly spotless/palantir isn't working.

If OJF supported spotless's import grouping and 2sp's, I'd switch in a heartbeat, as it would largely be a no-op change in formatting.

I'm leaving my current place of employment soon and was hoping to leave them all on Java 27 for both build and deploy, but without incurring mass format changes over several 100 repos....

@palantirtech Any chance we can get some resolution on this PR? It seems like it's starting to affect more and more folks.

@abashev

abashev commented Nov 10, 2026

Copy link
Copy Markdown

@talios I did a huge update for gradle plugin in OJF latest version - it was useless for me either. But I fixed support for configuration cache, build cache, added formatter jars into plugin so don't need to add repos in main project. If something is still preserve you from using the plugin please let me know 🙏

@glaucioscheibel

Copy link
Copy Markdown

I just updated the Palantir version in Spotless to 2.103.0, and it’s running on Java 27. Here on GitHub does not mention this version, but the mvnrepository site does.

@andrej-urvantsev

Copy link
Copy Markdown

Nope. It still fails:

mvn --version
Apache Maven 3.10.0 (c43a36b8d67be7e0805a411bc0898af1a51f5472)
Maven home: /Users/andrej.urvantsev/.sdkman/candidates/maven/current
Java version: 27.0.1, vendor: BellSoft, runtime: /Users/andrej.urvantsev/.sdkman/candidates/java/27.0.1.0+11-librca
Default locale: en_US, platform encoding: UTF-8, time zone: Europe/Stockholm
OS name: "mac os x", version: "27.2.1", arch: "aarch64", family: "mac
<palantirJavaFormat>
  <version>2.103.0</version>
  <style>PALANTIR</style>
  <formatJavadoc>true</formatJavadoc>
</palantirJavaFormat>
mvn spotless:apply

...

error: java.lang.NoSuchFieldError: Class com.sun.tools.javac.tree.JCTree$JCCompilationUnit does not have member field 'com.sun.tools.javac.tree.EndPosTable endPositions' (...)

@slachiewicz

Copy link
Copy Markdown
Author

@glaucioscheibel, @andrej-urvantsev — to clear this up: 2.103.0 does not contain the JDK 27 fix. It was published on Oct 27, and PR #1786 is still open, so no released version fixes either #1785 or #1799 yet.

@glaucioscheibel I suspect your build works because the JVM running Spotless is still JDK ≤ 26 (toolchain, .mvn/jvm.config, or the IDE's bundled Maven runtime). The crash is in the JVM that runs the formatter, not in the release you compile for — that would explain why it "runs on Java 27" for you while failing elsewhere.

@andrej-urvantsev Your stack trace is exactly what this PR fixes: develop still calls ((JCCompilationUnit) path.getCompilationUnit()).endPositions directly, which is the field JDK-8372948 removed in JDK 27 — hence NoSuchFieldError in 2.103.0. I verified develop has no other fix for this (nothing merged or re-implemented; the only PR with the end-position change is this one).

For the record, what's left to merge has been unchanged since Oct 20: the branch is green on CircleCI and merges cleanly; two maintainer-only actions remain — ticking Fix + Generate changelog entry in the changelog-app comment above, and a policy-bot approval. @crogoz, @pkoenig10 — over to you.

JDK-8372948 removed EndPosTable and JCCompilationUnit.endPositions and
re-ordered the four-argument ParserFactory.newParser. Trees now resolves
the end-position API once through a method handle and all three call
sites go through it; Trees.newParser passes the parser flags in the order
each JDK generation expects.
JDK 27 gives var declarations a VarTypeTree type instead of null, which the
visitors scanned to nothing ("expected token: 'var'"). Check for var before
the declared type, as google-java-format#1342 does; the binding-pattern check
compares the kind by name because Tree.Kind.VAR_TYPE is new in JDK 27.

Fixes palantir#1799
Trees reaches EndPosTable, JCTree.getEndPosition(EndPosTable) and
JCCompilationUnit.endPositions through method and var handles, which
native-image cannot resolve without metadata; google-java-format needed the
same three entries (google/google-java-format@ff157e3e46).
@talios

talios commented Nov 10, 2026

Copy link
Copy Markdown

@talios I did a huge update for gradle plugin in OJF latest version - it was useless for me either. But I fixed support for configuration cache, build cache, added formatter jars into plugin so don't need to add repos in main project. If something is still preserve you from using the plugin please let me know 🙏

I'd rather move this discussion off this PR since we're talking about OJF, but for me, it's more the extra pieces that spotless provides ( configurable import grouping - I like my whitespace separation of our own classes and common libraries, tho I could get over that on a new project - ideally, I don't want that churn on the current project), optional 2sp mode, which would solve spotless broken indent rules which break text blocks.

@andrej-urvantsev

Copy link
Copy Markdown

diffplug/spotless#3179

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet