diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java index ebee0ade961..fc3e390d644 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/Controllers.java @@ -305,6 +305,11 @@ public static void initialize(Stage stage) { .build()); } + if (HotSpotCrashDetector.hasPreviousCrash()) { + Controllers.dialogLater(new MessageDialogPane.Builder( + i18n("launcher.crash.previous_run"), null, MessageType.WARNING).ok(null).build()); + } + if (SettingsManager.userState().agreementVersionProperty().get() < 1) { JFXDialogLayout agreementPane = new JFXDialogLayout(); agreementPane.setHeading(new Label(i18n("launcher.agreement"))); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/HotSpotCrashDetector.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/HotSpotCrashDetector.java new file mode 100644 index 00000000000..ac5006ab565 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/HotSpotCrashDetector.java @@ -0,0 +1,228 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2026 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.util; + +import org.jackhuang.hmcl.util.io.IOUtils; +import org.jetbrains.annotations.NotNullByDefault; +import org.jetbrains.annotations.Nullable; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.time.Duration; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.jackhuang.hmcl.Metadata.CURRENT_DIRECTORY; +import static org.jackhuang.hmcl.util.logging.Logger.LOG; + +/// Detects a HotSpot error report associated with the previous HMCL session. +@NotNullByDefault +public final class HotSpotCrashDetector { + /// Matches HotSpot error report file names and captures their process IDs. + private static final Pattern ERROR_FILE_PATTERN = Pattern.compile("hs_err_pid(?\\d+)\\.log"); + + /// Matches uncompressed HMCL log file names and captures their start times. + private static final Pattern LOG_FILE_PATTERN = Pattern.compile("(?