From a24fea4a95a4bcf5b02d9be4b1c3c9ea929f77ac Mon Sep 17 00:00:00 2001 From: Glavo Date: Thu, 18 Sep 2025 20:04:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E7=A6=81=E6=AD=A2=E7=94=9F?= =?UTF-8?q?=E6=88=90=20JVM=20=E4=BC=98=E5=8C=96=E5=8F=82=E6=95=B0=20(#4507?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hmcl/game/HMCLGameRepository.java | 1 + .../hmcl/setting/VersionSetting.java | 14 ++++ .../versions/AdvancedVersionSettingPage.java | 9 ++- .../resources/assets/lang/I18N.properties | 1 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + .../jackhuang/hmcl/game/LaunchOptions.java | 15 +++- .../hmcl/launch/DefaultLauncher.java | 78 ++++++++++--------- 8 files changed, 80 insertions(+), 40 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 9ad0546ac..5a095fb10 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -413,6 +413,7 @@ public final class HMCLGameRepository extends DefaultGameRepository { .setPreLaunchCommand(vs.getPreLaunchCommand()) .setPostExitCommand(vs.getPostExitCommand()) .setNoGeneratedJVMArgs(vs.isNoJVMArgs()) + .setNoGeneratedOptimizingJVMArgs(vs.isNoOptimizingJVMArgs()) .setNativesDirType(vs.getNativesDirType()) .setNativesDir(vs.getNativesDir()) .setProcessPriority(vs.getProcessPriority()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java index 3b0a35b8b..dbf6964d7 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -380,6 +380,20 @@ public final class VersionSetting implements Cloneable, Observable { noJVMArgsProperty.set(noJVMArgs); } + private final BooleanProperty noOptimizingJVMArgsProperty = new SimpleBooleanProperty(this, "noOptimizingJVMArgs", false); + + public BooleanProperty noOptimizingJVMArgsProperty() { + return noOptimizingJVMArgsProperty; + } + + public boolean isNoOptimizingJVMArgs() { + return noOptimizingJVMArgsProperty.get(); + } + + public void setNoOptimizingJVMArgs(boolean noOptimizingJVMArgs) { + noOptimizingJVMArgsProperty.set(noOptimizingJVMArgs); + } + private final BooleanProperty notCheckJVMProperty = new SimpleBooleanProperty(this, "notCheckJVM", false); public BooleanProperty notCheckJVMProperty() { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java index 2cbf8e73f..fdbab21b1 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/AdvancedVersionSettingPage.java @@ -43,6 +43,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor private final JFXTextField txtPreLaunchCommand; private final JFXTextField txtPostExitCommand; private final OptionToggleButton noJVMArgsPane; + private final OptionToggleButton noOptimizingJVMArgsPane; private final OptionToggleButton noGameCheckPane; private final OptionToggleButton noJVMCheckPane; private final OptionToggleButton noNativesPatchPane; @@ -183,6 +184,10 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor noJVMArgsPane = new OptionToggleButton(); noJVMArgsPane.setTitle(i18n("settings.advanced.no_jvm_args")); + noOptimizingJVMArgsPane = new OptionToggleButton(); + noOptimizingJVMArgsPane.setTitle(i18n("settings.advanced.no_optimizing_jvm_args")); + noOptimizingJVMArgsPane.disableProperty().bind(noJVMArgsPane.selectedProperty()); + noGameCheckPane = new OptionToggleButton(); noGameCheckPane.setTitle(i18n("settings.advanced.dont_check_game_completeness")); @@ -199,7 +204,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor useNativeOpenALPane.setTitle(i18n("settings.advanced.use_native_openal")); workaroundPane.getContent().setAll( - nativesDirSublist, rendererPane, noJVMArgsPane, noGameCheckPane, + nativesDirSublist, rendererPane, noJVMArgsPane, noOptimizingJVMArgsPane, noGameCheckPane, noJVMCheckPane, noNativesPatchPane ); @@ -235,6 +240,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor noGameCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckGameProperty()); noJVMCheckPane.selectedProperty().bindBidirectional(versionSetting.notCheckJVMProperty()); noJVMArgsPane.selectedProperty().bindBidirectional(versionSetting.noJVMArgsProperty()); + noOptimizingJVMArgsPane.selectedProperty().bindBidirectional(versionSetting.noOptimizingJVMArgsProperty()); noNativesPatchPane.selectedProperty().bindBidirectional(versionSetting.notPatchNativesProperty()); useNativeGLFWPane.selectedProperty().bindBidirectional(versionSetting.useNativeGLFWProperty()); useNativeOpenALPane.selectedProperty().bindBidirectional(versionSetting.useNativeOpenALProperty()); @@ -276,6 +282,7 @@ public final class AdvancedVersionSettingPage extends StackPane implements Decor noGameCheckPane.selectedProperty().unbindBidirectional(versionSetting.notCheckGameProperty()); noJVMCheckPane.selectedProperty().unbindBidirectional(versionSetting.notCheckJVMProperty()); noJVMArgsPane.selectedProperty().unbindBidirectional(versionSetting.noJVMArgsProperty()); + noOptimizingJVMArgsPane.selectedProperty().unbindBidirectional(versionSetting.noOptimizingJVMArgsProperty()); noNativesPatchPane.selectedProperty().unbindBidirectional(versionSetting.notPatchNativesProperty()); useNativeGLFWPane.selectedProperty().unbindBidirectional(versionSetting.useNativeGLFWProperty()); useNativeOpenALPane.selectedProperty().unbindBidirectional(versionSetting.useNativeOpenALProperty()); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 2f2e7ae7d..56064f3d5 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1290,6 +1290,7 @@ settings.advanced.natives_directory.hint=This option is intended only for users Before proceeding, please make sure all libraries (e.g. lwjgl.dll, libopenal.so) are provided in your desired directory.\n\ Note: It is recommended to use a fully English-letters path for the specified local library file. Otherwise it may lead to game launch failure. settings.advanced.no_jvm_args=Do not add default JVM arguments +settings.advanced.no_optimizing_jvm_args=Do not add default JVM optimization arguments settings.advanced.precall_command=Pre-launch Command settings.advanced.precall_command.prompt=Commands to execute before the game launches settings.advanced.process_priority=Process Priority diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 215c21257..d01764c5f 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1080,6 +1080,7 @@ settings.advanced.natives_directory.default=預設 (由啟動器提供遊戲本 settings.advanced.natives_directory.default.version_id=<實例名稱> settings.advanced.natives_directory.hint=本選項提供給 Apple Silicon 等未受遊戲官方支援的平台來自訂遊戲本機庫。如果你不知道本選項的含義,請你不要修改本選項,否則會導致遊戲無法啟動。\n\n如果你要修改本選項,你需要保證自訂目錄下有遊戲所需的本機庫檔案,如 lwjgl.dll (liblwjgl.so), openal.dll (libopenal.so) 等檔案。啟動器不會幫你補全缺少的本機庫檔案。\n\n注意:建議指定的本機庫檔案路徑使用全英文字元,否則可能導致遊戲啟動失敗。 settings.advanced.no_jvm_args=不新增預設的 Java 虛擬機參數 +settings.advanced.no_optimizing_jvm_args=不自動添加 Java 虛擬機優化參數 settings.advanced.precall_command=遊戲啟動前執行指令 settings.advanced.precall_command.prompt=將在遊戲啟動前呼叫使用 settings.advanced.process_priority=處理程式優先度 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 21674164b..43603a3cb 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1091,6 +1091,7 @@ settings.advanced.natives_directory.default=默认 (由启动器提供游戏本 settings.advanced.natives_directory.default.version_id=<实例名称> settings.advanced.natives_directory.hint=本选项提供给 Apple Silicon 等未受游戏官方支持的平台来自定义游戏本地库。如果你不知道本选项的含义,请不要修改本选项,否则会导致游戏无法启动!\n\n如果你要修改本选项,你需要保证自定义文件夹下有游戏所需的本地库文件,如 lwjgl.dll (liblwjgl.so)、openal.dll (libopenal.so) 等文件。启动器不会帮你补全缺少的本地库文件!\n\n注意:指定的本地库文件路径建议只包含英文大小写字母、数字和下划线,否则可能会导致启动游戏失败。 settings.advanced.no_jvm_args=不添加默认的 Java 虚拟机参数 +settings.advanced.no_optimizing_jvm_args=不自动添加 Java 虚拟机优化参数 settings.advanced.precall_command=游戏启动前执行命令 settings.advanced.precall_command.prompt=将在游戏启动前调用 settings.advanced.process_priority=进程优先级 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java index 88c75da94..93d9a41b4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/game/LaunchOptions.java @@ -55,6 +55,7 @@ public class LaunchOptions implements Serializable { private String proxyUser; private String proxyPass; private boolean noGeneratedJVMArgs; + private boolean noGeneratedOptimizingJVMArgs; private String preLaunchCommand; private String postExitCommand; private NativesDirectoryType nativesDirType; @@ -226,6 +227,13 @@ public class LaunchOptions implements Serializable { return noGeneratedJVMArgs; } + /** + * Prevent game launcher from generating optimizing JVM arguments. + */ + public boolean isNoGeneratedOptimizingJVMArgs() { + return noGeneratedOptimizingJVMArgs; + } + /** * Command called before game launches. */ @@ -281,7 +289,7 @@ public class LaunchOptions implements Serializable { return daemon; } - public static class Builder { + public static final class Builder { private final LaunchOptions options = new LaunchOptions(); @@ -439,6 +447,11 @@ public class LaunchOptions implements Serializable { return this; } + public Builder setNoGeneratedOptimizingJVMArgs(boolean noGeneratedOptimizingJVMArgs) { + options.noGeneratedOptimizingJVMArgs = noGeneratedOptimizingJVMArgs; + return this; + } + public Builder setPreLaunchCommand(String preLaunchCommand) { options.preLaunchCommand = preLaunchCommand; return this; diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java index a60a2963e..09489492b 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -193,50 +193,52 @@ public class DefaultLauncher extends Launcher { final int javaVersion = options.getJava().getParsedVersion(); final boolean is64bit = options.getJava().getBits() == Bits.BIT_64; - res.addUnstableDefault("UnlockExperimentalVMOptions", true); - res.addUnstableDefault("UnlockDiagnosticVMOptions", true); + if (!options.isNoGeneratedOptimizingJVMArgs()) { + res.addUnstableDefault("UnlockExperimentalVMOptions", true); + res.addUnstableDefault("UnlockDiagnosticVMOptions", true); - // Using G1GC with its settings by default - if (javaVersion >= 8 - && res.noneMatch(arg -> "-XX:-UseG1GC".equals(arg) || (arg.startsWith("-XX:+Use") && arg.endsWith("GC")))) { - res.addUnstableDefault("UseG1GC", true); - res.addUnstableDefault("G1MixedGCCountTarget", "5"); - res.addUnstableDefault("G1NewSizePercent", "20"); - res.addUnstableDefault("G1ReservePercent", "20"); - res.addUnstableDefault("MaxGCPauseMillis", "50"); - res.addUnstableDefault("G1HeapRegionSize", "32m"); - } - - res.addUnstableDefault("OmitStackTraceInFastThrow", false); - - // JIT Options - if (javaVersion <= 8) { - res.addUnstableDefault("MaxInlineLevel", "15"); - } - if (is64bit && SystemInfo.getTotalMemorySize() > 4L * 1024 * 1024 * 1024) { - res.addUnstableDefault("DontCompileHugeMethods", false); - res.addUnstableDefault("MaxNodeLimit", "240000"); - res.addUnstableDefault("NodeLimitFudgeFactor", "8000"); - res.addUnstableDefault("TieredCompileTaskTimeout", "10000"); - res.addUnstableDefault("ReservedCodeCacheSize", "400M"); - if (javaVersion >= 9) { - res.addUnstableDefault("NonNMethodCodeHeapSize", "12M"); - res.addUnstableDefault("ProfiledCodeHeapSize", "194M"); + // Using G1GC with its settings by default + if (javaVersion >= 8 + && res.noneMatch(arg -> "-XX:-UseG1GC".equals(arg) || (arg.startsWith("-XX:+Use") && arg.endsWith("GC")))) { + res.addUnstableDefault("UseG1GC", true); + res.addUnstableDefault("G1MixedGCCountTarget", "5"); + res.addUnstableDefault("G1NewSizePercent", "20"); + res.addUnstableDefault("G1ReservePercent", "20"); + res.addUnstableDefault("MaxGCPauseMillis", "50"); + res.addUnstableDefault("G1HeapRegionSize", "32m"); } - if (javaVersion >= 8) { - res.addUnstableDefault("NmethodSweepActivity", "1"); + res.addUnstableDefault("OmitStackTraceInFastThrow", false); + + // JIT Options + if (javaVersion <= 8) { + res.addUnstableDefault("MaxInlineLevel", "15"); } - } + if (is64bit && SystemInfo.getTotalMemorySize() > 4L * 1024 * 1024 * 1024) { + res.addUnstableDefault("DontCompileHugeMethods", false); + res.addUnstableDefault("MaxNodeLimit", "240000"); + res.addUnstableDefault("NodeLimitFudgeFactor", "8000"); + res.addUnstableDefault("TieredCompileTaskTimeout", "10000"); + res.addUnstableDefault("ReservedCodeCacheSize", "400M"); + if (javaVersion >= 9) { + res.addUnstableDefault("NonNMethodCodeHeapSize", "12M"); + res.addUnstableDefault("ProfiledCodeHeapSize", "194M"); + } - if (is64bit && javaVersion == 25) { - res.addUnstableDefault("UseCompactObjectHeaders", true); - } + if (javaVersion >= 8) { + res.addUnstableDefault("NmethodSweepActivity", "1"); + } + } - // As 32-bit JVM allocate 320KB for stack by default rather than 64-bit version allocating 1MB, - // causing Minecraft 1.13 crashed accounting for java.lang.StackOverflowError. - if (!is64bit) { - res.addDefault("-Xss", "1m"); + if (is64bit && javaVersion == 25) { + res.addUnstableDefault("UseCompactObjectHeaders", true); + } + + // As 32-bit JVM allocate 320KB for stack by default rather than 64-bit version allocating 1MB, + // causing Minecraft 1.13 crashed accounting for java.lang.StackOverflowError. + if (!is64bit) { + res.addDefault("-Xss", "1m"); + } } if (javaVersion == 16)