Skip to content

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

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

slachiewicz wants to merge 3 commits into
palantir:developfrom
slachiewicz: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 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-integration-testing that referenced this pull request Oct 12, 2026
palantir-java-format crashes on JDK 27 (palantir/palantir-java-format#1786). Drop the profile once maven-parent ships a fixed release.
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
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 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).
@talios

talios commented Oct 13, 2026

Copy link
Copy Markdown

Hopefully this and #1786 can get merged and released soon.

@crogoz

crogoz commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

hey @slachiewicz thanks for putting this PR up! I think circleci has not run because of the permission error see here: We did not run this pipeline because the project has been suspended. Please fill out this form if you want to request a review: https://forms.gle/iZESLhcG5MPzLhWS7.
Our checks run on other PRs/branches, so I wonder if this is something that needs to be signed on your side/this was brought in by a commit from other people.

@slachiewicz

Copy link
Copy Markdown
Author

yes thanks. looks like my account on cirle is blocked. Feel free to cherry-pick or revirite my PR - that woudl be faster.

@robinsturmeit

Copy link
Copy Markdown

Hi @slachiewicz,
Your user account on CircleCI was suspended a long time ago via automation. It was before we introduced timestamps (which was three years ago or so), so long past any log retention. I reversed the suspension, your build should run now. Sorry for the inconvenience.

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
@talios

talios commented Oct 19, 2026

Copy link
Copy Markdown

So close.. I thought the changelog was updated? Not sure why that check is failing now, or the policy-bot?

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).
@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.

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

Labels

None yet

Projects

None yet

5 participants