diff --git a/flake.nix b/flake.nix index c22904e..bfa08b4 100644 --- a/flake.nix +++ b/flake.nix @@ -107,9 +107,25 @@ classpath="$classpath''${classpath:+:}$jar" done + # The CDS archive records launch-time module/classpath properties, including + # Nix store paths. Key it by this build's launch shape so stale archives from a + # previous package path cannot be reused, and pass the flags on java's command + # line so terminal child processes do not inherit them through JAVA_TOOL_OPTIONS. + cdsArchive="app-$(printf '%s\n' \ + "${pkgs.jdk25}" \ + "$out" \ + "$classpath" \ + "$out/share/jprototerm/javafx" \ + "--enable-native-access=ALL-UNNAMED,javafx.graphics" \ + "--add-modules=javafx.controls,javafx.fxml" \ + "com.gregor.jprototerm.Main" \ + | sha256sum | cut -c1-16).jsa" + makeWrapper "${pkgs.jdk25}/bin/java" "$out/bin/jprototerm" \ --run 'export JPROTOTERM_HOST_LD_LIBRARY_PATH="''${LD_LIBRARY_PATH:-}"' \ - --run 'cdsDir="''${XDG_CACHE_HOME:-$HOME/.cache}/jprototerm"; mkdir -p "$cdsDir"; export JAVA_TOOL_OPTIONS="-XX:+AutoCreateSharedArchive -XX:SharedArchiveFile=$cdsDir/app.jsa ''${JAVA_TOOL_OPTIONS:-}"' \ + --run 'cdsDir="''${XDG_CACHE_HOME:-$HOME/.cache}/jprototerm"; mkdir -p "$cdsDir"' \ + --add-flags "-XX:+AutoCreateSharedArchive" \ + --add-flags "-XX:SharedArchiveFile=\$cdsDir/$cdsArchive" \ --add-flags "--enable-native-access=ALL-UNNAMED,javafx.graphics" \ --add-flags "--module-path $out/share/jprototerm/javafx" \ --add-flags "--add-modules javafx.controls,javafx.fxml" \ diff --git a/src/main/java/com/gregor/jprototerm/ShellSession.java b/src/main/java/com/gregor/jprototerm/ShellSession.java index a1f4c9f..826759e 100644 --- a/src/main/java/com/gregor/jprototerm/ShellSession.java +++ b/src/main/java/com/gregor/jprototerm/ShellSession.java @@ -96,10 +96,26 @@ public final class ShellSession implements AutoCloseable { // These are jprototerm's own runtime settings, not the user's shell environment. environment.remove("GDK_BACKEND"); environment.remove("JLIBGHOSTTY_LIBRARY"); - // The wrapper exports this to point our own JVM at its CDS archive; left in place it - // would make unrelated java/gradle invocations inside the terminal load jprototerm's - // archive (and print the "Picked up JAVA_TOOL_OPTIONS" banner). - environment.remove("JAVA_TOOL_OPTIONS"); + sanitizeJavaToolOptions(environment); + } + + private static void sanitizeJavaToolOptions(Map environment) { + String javaToolOptions = environment.get("JAVA_TOOL_OPTIONS"); + if (javaToolOptions == null + || !javaToolOptions.contains("-XX:SharedArchiveFile=") + || !javaToolOptions.contains("/jprototerm/app")) { + return; + } + + String sanitized = javaToolOptions + .replaceAll("(^|\\s)-XX:\\+AutoCreateSharedArchive(?=\\s|$)", " ") + .replaceAll("(^|\\s)-XX:SharedArchiveFile=\\S*/jprototerm/app\\S*(?=\\s|$)", " ") + .trim(); + if (sanitized.isEmpty()) { + environment.remove("JAVA_TOOL_OPTIONS"); + } else { + environment.put("JAVA_TOOL_OPTIONS", sanitized); + } } public void startReading(TerminalPane pane) {