Skip to content

fix(desktop): drop the class data sharing archive, which installed apps never used - #436

Merged
linroid merged 2 commits into
mainfrom
fix/drop-desktop-cds-archive
Oct 8, 2026
Merged

linroid merged 2 commits into
mainfrom
fix/drop-desktop-cds-archive

Conversation

@linroid

@linroid linroid commented Oct 8, 2026

Copy link
Copy Markdown
Owner

The AppCDS archive added in #421, ketch.jsa, never applied to an installed app. This removes it.

Why it never worked

  • JDK 21 checks the build machine's paths. FileMapInfo::validate_shared_path_table() calls SharedClassPathEntry::validate() on each jar at the absolute path it had when the archive was dumped, checking its size and modification time. Only the JDK's modules file is looked up at its current location. A missing path ("Required classpath entry does not exist") rejects the whole archive. That happens before validate_app_class_paths() tries its "moved together" prefix match, which only compares names.
  • The installed release loaded 0 classes from the archive. A moved local image used it (11,225 classes) only while its build folder still existed, and 0 once that folder was renamed away. The KDoc's "sizes, not timestamps" and "accepts the app's folder having moved" were both wrong.
  • No JDK 21 option skips this check. ArchiveRelocationMode only sets the memory address the archive is mapped at.

Alternatives considered

  • Dumping at the default install path (/Applications/Ketch.app, C:\Program Files\Ketch, /opt/ketch): would still fail. jpackage's DMG copy gives every jar a new modification time (1791430891 in the image, 1791430967 in the DMG). The MSI and deb are built from a copy too, and MSI cabinets store times only to 2 seconds in local time.
  • JDK 25: AOTClassLocationConfig::check_classpaths checks the jars where they are now, but still compares their modification times, so packaged builds hit the same problem.
  • -XX:+AutoCreateSharedArchive: needs a path each user can write to. JDK 21's launcher config only expands $APPDIR, $BINDIR and $ROOTDIR, and the installed app folder is read-only (on macOS, writing into it breaks the code signature).

So the archive cost about 70 MB installed and 15 MB of the DMG for no gain.

Changes

  • Removes CdsArchive, its three -XX launcher options, the dump step, recordCdsClassList and app/desktop/cds/app.classlist.
  • Rewrites the App Size bullet in AGENTS.md and the testing.md paragraph to say why there is no archive, and how to check a launch with JAVA_TOOL_OPTIONS=-Xlog:class+load,cds:file=… and the build folder renamed away.

Testing

createDistributable, then the image copied with ditto and the build's app folder renamed away. The copy has no ketch.jsa and its config passes no CDS flags. It starts without CDS warnings, and codesign --verify --strict passes on jpackage's original signature.

Conflict with #435

#435 edits the ketch.jsa paragraph in testing.md, which this PR deletes, and adds an -Xlog line next to the removed launcher options. Whichever merges second should keep #435's -Xlog line and this PR's testing.md text.

Possible follow-up

On JDK 25 the launcher config can read environment variables, so -XX:+AutoCreateSharedArchive with a per-user cache path would build the archive on the user's machine, where paths and times match. The native messaging host also starts a JVM and would share that archive, and quitting takes longer while it is written.

…ps never used

The JVM checks every jar an AppCDS archive names at the absolute path it had when the
archive was dumped (SharedClassPathEntry::validate in JDK 21's filemap.cpp), with its
size and modification time, before its "moved together" prefix match. On a user's
machine the CI paths don't exist, so the whole archive was rejected: the installed
release loaded 0 classes from it. A moved local image only used it while the build
folder still existed.

No JDK 21 option avoids the check. Dumping at the default install path wouldn't help
either: jpackage's DMG copy gives every jar a new modification time, which JDK 25's
relocatable AOTClassLocation check still compares. So the archive cost about 70 MB
installed and 15 MB of the DMG for nothing.

Removes CdsArchive, its launcher options, the dump hook, recordCdsClassList and
cds/app.classlist, and says why in AGENTS.md and testing.md.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

…archive

# Conflicts:
#	app/desktop/build.gradle.kts
#	docs/development/testing.md
@linroid
linroid merged commit 39fa94a into main Oct 8, 2026
@linroid
linroid deleted the fix/drop-desktop-cds-archive branch October 8, 2026 03:51
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