Skip to content

Preserve applicationDefaultJvmArgs in distribution start script#378

Merged
ryandens merged 1 commit into
mainfrom
worktree-fix-app-default-jvm-args
Jul 7, 2026
Merged

Preserve applicationDefaultJvmArgs in distribution start script#378
ryandens merged 1 commit into
mainfrom
worktree-fix-app-default-jvm-args

Conversation

@ryandens

@ryandens ryandens commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Problem

Fixes #95. Applying the application-distribution plugin dropped/mangled JVM args a consumer set via applicationDefaultJvmArgs.

On Unix the plugin collapsed Gradle's individually-quoted options into a single double-quoted string (needed so $APP_HOME in the agent path expands). But collapsing the per-option quotes means the launcher word-splits $DEFAULT_JVM_OPTS, so any option whose value contains a space breaks:

applicationDefaultJvmArgs = ['-Dgreeting=hello world']

produced DEFAULT_JVM_OPTS="-javaagent:$APP_HOME/... -Dgreeting=hello world", which the shell splits into -Dgreeting=hello and world. world is then treated as the main class:

Error: Could not find or load main class world

A space-free arg like -Dabc=123 survived by luck, which is why the existing test didn't catch it.

Fix

Keep every option its own quoted token. The Unix DEFAULT_JVM_OPTS value stays wrapped in outer double quotes so $APP_HOME still expands, but each option's own quotes are now backslash-escaped so they survive into the value and the launcher's xargs pass parses them back out intact:

DEFAULT_JVM_OPTS="\"-javaagent:$APP_HOME/agent-libs/otel.jar\" \"-Dgreeting=hello world\" \"-Dabc=123\""

Multiple agents are joined with an escaped-quote separator for the same reason. Windows already kept literal per-option quotes and is unchanged.

Verification

  • New functional test preserves applicationDefaultJvmArgs containing spaces in application distribution runs the installed distribution and asserts the space-containing arg reaches the JVM as a single argument. It fails on the old code and passes on the fix.
  • Verified end-to-end against a real project using the OpenTelemetry javaagent: the agent attaches and both -Dgreeting=hello world and -Dabc=123 reach the JVM intact.
  • Existing distribution/no-agent/multi-agent tests updated to the new script format and pass; unit tests and spotless pass.

🤖 Generated with Claude Code

Note

Preserve applicationDefaultJvmArgs containing spaces in distribution start scripts

  • Updates Platform.UNIX in Platform.kt to wrap each JVM option as an individually quoted, backslash-escaped token inside DEFAULT_JVM_OPTS, preventing shell word-splitting on options with spaces.
  • Fixes placeholder-removal logic in JavaagentAwareStartScriptGenerator.kt to strip the escaped, quoted placeholder token cleanly when no agents are present, avoiding stray backslashes.
  • Behavioral Change: DEFAULT_JVM_OPTS on Unix now uses the form "\"opt1\" \"opt2\"" instead of a single quoted string; existing scripts that parse this value directly may see a different format.
📊 Macroscope summarized ffcb971. 3 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted

🗂️ Filtered Issues

No issues evaluated.

The application-distribution plugin templated the `-javaagent` option into
`CreateStartScripts.defaultJvmOpts` and then, on Unix, collapsed the
individually-quoted options into a single double-quoted string so that the
embedded `$APP_HOME` in the agent path would expand at assignment time.

Collapsing the per-option quotes discards the boundary Gradle's native start
script relies on: the launcher word-splits `$DEFAULT_JVM_OPTS`, so any option
whose value contains a space (e.g. `-Dgreeting=hello world`) is split into
multiple arguments -- `world` then gets treated as the main class and the app
fails to start. A single space-free option like `-Dabc=123` survived by luck,
which is why the existing test did not catch it.

Keep every option its own quoted token. The Unix `DEFAULT_JVM_OPTS` value is
still wrapped in outer double quotes (so `$APP_HOME` expands), but each
option's own quotes are now backslash-escaped so they survive into the value
and the launcher's `xargs` pass parses them back out intact. Multiple agents
are joined with an escaped-quote separator for the same reason. Windows, which
already kept literal per-option quotes, is unchanged.

Adds a functional test that runs the installed distribution with a
space-containing `applicationDefaultJvmArg` and asserts the value reaches the
JVM as a single argument.

Fixes #95

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ryandens ryandens marked this pull request as ready for review July 7, 2026 04:36
@ryandens ryandens force-pushed the worktree-fix-app-default-jvm-args branch from 29c395a to ffcb971 Compare July 7, 2026 04:37
@ryandens ryandens enabled auto-merge (squash) July 7, 2026 04:42
@ryandens ryandens merged commit c4bbb2e into main Jul 7, 2026
4 checks passed
@ryandens ryandens deleted the worktree-fix-app-default-jvm-args branch July 7, 2026 04:44
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.

Plugin overwrites applicationDefaultJvmArgs

1 participant