Skip to content

JavaFX app: launch splash never dismissed (overlays app on macOS, stuck behind app on Linux) #471

Description

@FDelporte

Summary

For a JavaFX desktop app packaged with jDeploy, the launch splash screen (splash.png/splash.gif) is never dismissed once the app's main window is up and running:

  • macOS: the splash stays on top of the app window, blocking interaction entirely — the app is effectively unusable until the user manually kills/hides the splash.
  • Linux: the app window does come to the front and is usable, but the splash remains rendered underneath it (never actually closed/torn down).

This can be seen in release 1.2.0 of MelodyMatrix, available at https://github.com/codewriterbv/melodymatrix-app-releases/releases#release-1.2.0

Environment

  • jDeploy 6.1.1 (via shannah/jdeploy@master GitHub Action)
  • Java 25, JavaFX 26 (-Djavafx.enablePreview=true --enable-native-access=javafx.graphics)
  • jdeploy config: "javafx": true, bundles for mac-x64, mac-arm64, win, linux
  • Repro'd across multiple app releases (regressed between our own two releases roughly two weeks apart, same jDeploy default version — see below)

What we ruled out before filing

  1. Splash image itself — swapped an animated splash.gif back to a plain static splash.png; identical behavior either way. Not image-format-related.
  2. jDeploy version drift — confirmed via our GitHub Actions run logs that both the last known-good release and the regressed one resolved shannah/jdeploy@master using the same jdeploy_version: 6.1.1 default (per action.yml history, that default was set on 2026-03-15 and hadn't changed across either build date). So this isn't a case of @master picking up a different jDeploy release between builds.
  3. App-side SplashScreen API usage — our app never calls java.awt.SplashScreen anywhere; we rely entirely on jDeploy's own splash handling via the splash.png/splash.gif filename convention.
  4. New blocking startup code — audited our app's JavaFX startup path (everything running on the FX Application Thread before/around Stage.show()) against our last known-good release; no new blocking/synchronous call was introduced there.
  5. Shaded-jar service merging — we added a ServicesResourceTransformer to our Maven Shade config around the same time and suspected it might be involved; inspected the merged META-INF/services/* entries in the built jar and they're all correct/clean (no duplicate or conflicting SPI providers).
  6. Workaround confirms isolation to the splash mechanism: removing splash.png/splash.gif entirely (so jDeploy shows no launch splash at all) makes the app launch and behave normally on both platforms. This confirms the app itself starts and becomes ready correctly — the bug is specifically in how/whether jDeploy detects readiness and dismisses the splash for a JavaFX app.

Question for maintainers

Since JavaFX doesn't create an AWT window, it won't trigger whatever "close splash when a window appears" heuristic might work for Swing/AWT apps. How is splash dismissal supposed to work for JavaFX apps specifically — is it a window-enumeration poll, a fixed timeout, or does the app need to signal readiness explicitly (e.g. a marker on stdout, a file, an exit code)? Is this expected to be reliable/deterministic, or could it be a timing race that's more likely to lose on some machines than others (which would explain the mac vs. Linux difference we saw)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions