Skip to content

Dist: run the runtime with compact object headers and ship its base CDS archive - #1389

Closed
Frotty wants to merge 2 commits into
masterfrom
compact-object-headers
Closed

Frotty wants to merge 2 commits into
masterfrom
compact-object-headers

Conversation

@Frotty

@Frotty Frotty commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

What

The compiler and the language server hold millions of small objects, so they should run with compact object headers (-XX:+UseCompactObjectHeaders, a product flag since JDK 25). Users could already ask for it in wurst.javaOpts, and CI exports it for the tests; nothing in the distribution made it the default. Giving the option twice (launcher plus javaOpts or JAVA_TOOL_OPTIONS) is harmless: the JVM takes the last one, and the checks below cover it.

A JVM uses a base CDS archive only for the object header mode it was started with. #1386 made the base archive with jlink --generate-cds-archive, which writes it for the options of the JVM jlink starts, so it came out as classes.jsa on a developer machine and as classes_coh.jsa on CI (which exports JAVA_TOOL_OPTIONS=-XX:+UseCompactObjectHeaders). Making compact headers the default needs the archive to be the one for that mode, whatever the build machine exports.

  • deploy.gradle no longer asks jlink for the archive. After jlink it runs java -XX:+UseCompactObjectHeaders -Xshare:dump on the image, with JAVA_TOOL_OPTIONS, _JAVA_OPTIONS and JDK_JAVA_OPTIONS removed, and ships only that archive (classes_coh.jsa, 14.6 MB). macOS copies a full JDK, which has it.
  • assembleSlimCompilerDist starts the runtime with -XX:+UseCompactObjectHeaders -Xshare:on, which fails when there is no usable archive. That replaces looking for a file name.
  • launchers/wurstscript, wurstscript.cmd, grill, grill.cmd pass -XX:+UseCompactObjectHeaders.
  • AGENTS.md ("Language server startup archive") and CHANGELOG.md state the contract.

Companion changes: wurst4vscode (the language server's own launch) and grill (WurstSetup) pass the same flag.

Measured

Language server on castle fight, start to the initial build being ready, three interleaved starts each (full Temurin 25 JDK):

default headers -XX:+UseCompactObjectHeaders
ready, median 21.13 s 20.70 s
heap after a full GC 488 MB (all three) 457 MB (−6%)

The built distribution from this branch (runtime with classes_coh.jsa, extension flags -XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=… -Xlog:disable): 19.0 s for the first start (which writes the 30.6 MB application archive), then 18.0 s and 18.0 s.

Checks

  • ./gradlew assembleSlimCompilerDist on Windows: bin/server holds classes_coh.jsa only; java -XX:+UseCompactObjectHeaders -Xshare:on -version exits 0, and without the option it exits 1 (no archive for that header mode), so the guard is meaningful.
  • The same build with JAVA_TOOL_OPTIONS="-XX:+UseCompactObjectHeaders -XX:+UseStringDeduplication --enable-native-access=ALL-UNNAMED" set (the CI case): the same single archive.
  • The option given twice (-XX:+UseCompactObjectHeaders in the launcher and again in wurst.javaOpts, or in JAVA_TOOL_OPTIONS as well) starts with -Xshare:on, exit 0; so does on, off, on.
  • assembleSlimCompilerDist is a Sync now: a stale classes.jsa and a stray file left in build/dist/slim-win-x64 by an earlier build are removed by the next run.
  • A second run reuses the configuration cache entry and is up to date.
  • Not run here: the Linux and macOS distributions (CI builds them; the -Xshare:on start fails the build if a runtime has no usable archive).

…DS archive

The heap of the compiler and the language server is millions of small objects, and compact object
headers took 6% off the heap of the language server on castle fight (488 to 457 MB after a collection)
at the same start time. A JVM uses a base CDS archive only for the object header mode it was started
with, so the runtime ships the archive for that mode and every launcher passes the option.

- jlink no longer makes the archive: it writes it for the options of the JVM it starts, which the
  JAVA_TOOL_OPTIONS of the build machine change (CI exports -XX:+UseCompactObjectHeaders, which left
  only classes_coh.jsa). The build runs java -XX:+UseCompactObjectHeaders -Xshare:dump on the image
  instead, with the option variables removed, and ships only that archive.
- assembleSlimCompilerDist starts the runtime with -Xshare:on, which fails without a usable archive,
  instead of looking for a file name.
- The launchers (wurstscript, grill, and their .cmd files) pass -XX:+UseCompactObjectHeaders.
@Frotty

Frotty commented Oct 8, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-08T12:59:19.785574Z 087c8ae Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4b4f61a2e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread de.peeeq.wurstscript/deploy.gradle
… stays in it

The folder is zipped as it is. A Copy only adds to it, so a checkout whose dist folder came from
an earlier build (with classes.jsa, the archive of the other header mode) shipped both archives.
@Frotty

Frotty commented Oct 8, 2026

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 087c8ae245

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Frotty

Frotty commented Oct 8, 2026

Copy link
Copy Markdown
Member Author

Closing: the shipped JRE is being upgraded to 27 by another change, which makes this rework unnecessary.

@Frotty Frotty closed this Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant