From afe6bc7456c0408b3380d1454d770323e96f5f29 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 10 Jul 2021 23:10:04 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=20JVM=20=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E4=BC=98=E5=85=88=E4=BA=8E=E9=BB=98=E8=AE=A4=E5=8F=82=E6=95=B0?= =?UTF-8?q?=20(#903)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * close #885: use the GC selected by user by default * fix: default JVM args conflict with user args * Options take precedence over JVM args * compile huge methods by default * update settings.advanced.jvm_args text * Using JVM args suppression options * update settings.advanced.jvm_args text --- .../resources/assets/lang/I18N.properties | 2 +- .../resources/assets/lang/I18N_es.properties | 2 +- .../resources/assets/lang/I18N_zh.properties | 2 +- .../assets/lang/I18N_zh_CN.properties | 2 +- .../hmcl/launch/DefaultLauncher.java | 67 ++++++++++-------- .../hmcl/util/platform/CommandBuilder.java | 68 +++++++++++++++++-- 6 files changed, 105 insertions(+), 38 deletions(-) diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 6c411b367..ce7098497 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -364,7 +364,7 @@ settings.advanced.dont_check_jvm_validity=Don't check whether JVM can launch the settings.advanced.game_dir.default=Standard (.minecraft/) settings.advanced.game_dir.independent=Independent (.minecraft/versions//, except for assets and libraries) settings.advanced.java_permanent_generation_space=PermGen Space/MB -settings.advanced.jvm_args=Java VM Arguments +settings.advanced.jvm_args=Java VM Arguments (overriding defaults) settings.advanced.launcher_visibility.close=Close the launcher when the game launched. settings.advanced.launcher_visibility.hide=Hide the launcher when the game launched. settings.advanced.launcher_visibility.hide_and_reopen=Hide the launcher and re-open when game closes. diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 052424768..04d43767a 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -335,7 +335,7 @@ settings.advanced.dont_check_jvm_validity=No verificar si JVM puede lanzar el ju settings.advanced.game_dir.default=Por defecto (.minecraft/) settings.advanced.game_dir.independent=Independiente (.minecraft/versions//, excepto assets,libraries) settings.advanced.java_permanent_generation_space=PermGen Space/MB -settings.advanced.jvm_args=Java VM Arguments +settings.advanced.jvm_args=Java VM Arguments (overriding defaults) settings.advanced.launcher_visibility.close=Cerrar launcher cuando juego es iniciado. settings.advanced.launcher_visibility.hide=Esconder launcher cuando juego is iniciado. settings.advanced.launcher_visibility.hide_and_reopen=Esconder launcher y reabrir cuando juego cierre. diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 627c47360..8154e75a2 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -358,7 +358,7 @@ settings.advanced.dont_check_jvm_validity=不檢查 JVM 與遊戲的相容性 settings.advanced.game_dir.default=預設(.minecraft/) settings.advanced.game_dir.independent=各版本獨立(.minecraft/versions/<版本名>/,除 assets、libraries) settings.advanced.java_permanent_generation_space=記憶體永久儲存區域(不必填寫,格式: MB) -settings.advanced.jvm_args=Java 虛擬機參數(不必填寫) +settings.advanced.jvm_args=Java 虛擬機參數(不必填寫,覆蓋默認設置) settings.advanced.launcher_visibility.close=遊戲啟動後結束啟動器 settings.advanced.launcher_visibility.hide=遊戲啟動後隱藏啟動器 settings.advanced.launcher_visibility.hide_and_reopen=隱藏啟動器並在遊戲結束後重新開啟 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 650c4e055..b48429912 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -364,7 +364,7 @@ settings.advanced.dont_check_jvm_validity=不检查 JVM 与游戏的兼容性 settings.advanced.game_dir.default=默认(.minecraft/) settings.advanced.game_dir.independent=各版本独立(.minecraft/versions/<版本名>/,除 assets、libraries) settings.advanced.java_permanent_generation_space=内存永久保存区域(不必填写,单位 MB) -settings.advanced.jvm_args=Java 虚拟机参数(不必填写) +settings.advanced.jvm_args=Java 虚拟机参数(不必填写,覆盖默认设置) settings.advanced.launcher_visibility.close=游戏启动后结束启动器 settings.advanced.launcher_visibility.hide=游戏启动后隐藏启动器 settings.advanced.launcher_visibility.hide_and_reopen=隐藏启动器并在游戏结束后重新打开 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 f25075477..291796068 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -52,7 +52,6 @@ import static org.jackhuang.hmcl.util.Lang.mapOf; import static org.jackhuang.hmcl.util.Pair.pair; /** - * * @author huangyuhui */ public class DefaultLauncher extends Launcher { @@ -84,53 +83,63 @@ public class DefaultLauncher extends Launcher { if (!options.isNoGeneratedJVMArgs()) { appendJvmArgs(res); - res.add("-Dminecraft.client.jar=" + repository.getVersionJar(version)); + res.addDefault("-Dminecraft.client.jar=", repository.getVersionJar(version).toString()); if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) { - res.add("-Xdock:name=Minecraft " + version.getId()); - res.add("-Xdock:icon=" + repository.getAssetObject(version.getId(), version.getAssetIndex().getId(), "icons/minecraft.icns").getAbsolutePath()); + res.addDefault("-Xdock:name=", "Minecraft " + version.getId()); + res.addDefault("-Xdock:icon=", repository.getAssetObject(version.getId(), version.getAssetIndex().getId(), "icons/minecraft.icns").getAbsolutePath()); } if (OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS) - res.add("-Duser.home=" + options.getGameDir().getParent()); + res.addDefault("-Duser.home=", options.getGameDir().getParent()); - // Force using G1GC with its settings + // Using G1GC with its settings by default if (options.getJava().getParsedVersion() >= JavaVersion.JAVA_8) { - res.add("-XX:+UnlockExperimentalVMOptions"); - res.add("-XX:+UseG1GC"); - res.add("-XX:G1NewSizePercent=20"); - res.add("-XX:G1ReservePercent=20"); - res.add("-XX:MaxGCPauseMillis=50"); - res.add("-XX:G1HeapRegionSize=16M"); + boolean addG1Args = true; + for (String javaArg : options.getJavaArguments()) { + if ("-XX:-UseG1GC".equals(javaArg) || (javaArg.startsWith("-XX:+Use") && javaArg.endsWith("GC"))) { + addG1Args = false; + break; + } + } + if (addG1Args) { + res.addUnstableDefault("UnlockExperimentalVMOptions", true); + res.addUnstableDefault("UseG1GC", true); + res.addUnstableDefault("G1NewSizePercent", "20"); + res.addUnstableDefault("G1ReservePercent", "20"); + res.addUnstableDefault("MaxGCPauseMillis", "50"); + res.addUnstableDefault("G1HeapRegionSize", "16m"); + } } if (options.getMetaspace() != null && options.getMetaspace() > 0) if (options.getJava().getParsedVersion() < JavaVersion.JAVA_8) - res.add("-XX:PermSize= " + options.getMetaspace() + "m"); + res.addDefault("-XX:PermSize=", options.getMetaspace() + "m"); else - res.add("-XX:MetaspaceSize=" + options.getMetaspace() + "m"); + res.addDefault("-XX:MetaspaceSize=", options.getMetaspace() + "m"); - res.add("-XX:-UseAdaptiveSizePolicy"); - res.add("-XX:-OmitStackTraceInFastThrow"); - res.add("-Xmn128m"); + res.addUnstableDefault("UseAdaptiveSizePolicy", false); + res.addUnstableDefault("OmitStackTraceInFastThrow", false); + res.addUnstableDefault("DontCompileHugeMethods", false); + res.addDefault("-Xmn", "128m"); // 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 (options.getJava().getPlatform() == Platform.BIT_32) { - res.add("-Xss1M"); + res.addDefault("-Xss", "1m"); } if (options.getMaxMemory() != null && options.getMaxMemory() > 0) - res.add("-Xmx" + options.getMaxMemory() + "m"); + res.addDefault("-Xmx", options.getMaxMemory() + "m"); if (options.getMinMemory() != null && options.getMinMemory() > 0) - res.add("-Xms" + options.getMinMemory() + "m"); + res.addDefault("-Xms", options.getMinMemory() + "m"); if (options.getJava().getParsedVersion() == JavaVersion.JAVA_16) - res.add("--illegal-access=permit"); + res.addDefault("--illegal-access=", "permit"); - res.add("-Dfml.ignoreInvalidMinecraftCertificates=true"); - res.add("-Dfml.ignorePatchDiscrepancies=true"); + res.addDefault("-Dfml.ignoreInvalidMinecraftCertificates=", "true"); + res.addDefault("-Dfml.ignorePatchDiscrepancies=", "true"); } Proxy proxy = options.getProxy(); @@ -140,13 +149,13 @@ public class DefaultLauncher extends Launcher { String host = address.getHostString(); int port = address.getPort(); if (proxy.type() == Proxy.Type.HTTP) { - res.add("-Dhttp.proxyHost=" + host); - res.add("-Dhttp.proxyPort=" + port); - res.add("-Dhttps.proxyHost=" + host); - res.add("-Dhttps.proxyPort=" + port); + res.addDefault("-Dhttp.proxyHost=", host); + res.addDefault("-Dhttp.proxyPort=", String.valueOf(port)); + res.addDefault("-Dhttps.proxyHost=", host); + res.addDefault("-Dhttps.proxyPort=", String.valueOf(port)); } else if (proxy.type() == Proxy.Type.SOCKS) { - res.add("-DsocksProxyHost=" + host); - res.add("-DsocksProxyPort=" + port); + res.addDefault("-DsocksProxyHost=", host); + res.addDefault("-DsocksProxyPort=", String.valueOf(port)); } } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/CommandBuilder.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/CommandBuilder.java index b79c4278b..3eec70312 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/CommandBuilder.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/CommandBuilder.java @@ -19,15 +19,20 @@ package org.jackhuang.hmcl.util.platform; import org.jackhuang.hmcl.util.StringUtils; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; +import java.util.*; import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.util.Logging.LOG; + public final class CommandBuilder { + private static final Pattern UNSTABLE_OPTION_PATTERN = Pattern.compile("-XX:(?[a-zA-Z0-9]+)=(?.*)"); + private static final Pattern UNSTABLE_BOOLEAN_OPTION_PATTERN = Pattern.compile("-XX:(?[+\\-])(?[a-zA-Z0-9]+)"); + private final OperatingSystem os; - private List raw = new LinkedList<>(); + private final List raw = new LinkedList<>(); public CommandBuilder() { this(OperatingSystem.CURRENT_OS); @@ -75,13 +80,66 @@ public final class CommandBuilder { return this; } + public CommandBuilder addDefault(String opt) { + for (Item item : raw) { + if (item.arg.equals(opt)) { + return this; + } + } + raw.add(new Item(opt, true)); + return this; + } + + public CommandBuilder addDefault(String opt, String value) { + for (Item item : raw) { + if (item.arg.startsWith(opt)) { + LOG.info("Default option '" + opt + value + "' is suppressed by '" + item.arg + "'"); + return this; + } + } + raw.add(new Item(opt + value, true)); + return this; + } + + public CommandBuilder addUnstableDefault(String opt, boolean value) { + for (Item item : raw) { + final Matcher matcher = UNSTABLE_BOOLEAN_OPTION_PATTERN.matcher(item.arg); + if (matcher.matches()) { + if (matcher.group("key").equals(opt)) { + return this; + } + } + } + + if (value) { + raw.add(new Item("-XX:+" + opt, true)); + } else { + raw.add(new Item("-XX:-" + opt, true)); + } + return this; + } + + public CommandBuilder addUnstableDefault(String opt, String value) { + for (Item item : raw) { + final Matcher matcher = UNSTABLE_OPTION_PATTERN.matcher(item.arg); + if (matcher.matches()) { + if (matcher.group("key").equals(opt)) { + return this; + } + } + } + + raw.add(new Item("-XX:" + opt + "=" + value, true)); + return this; + } + public boolean removeIf(Predicate pred) { return raw.removeIf(i -> pred.test(i.arg)); } @Override public String toString() { - return String.join(" ", raw.stream().map(i -> i.parse ? parse(i.arg) : i.arg).collect(Collectors.toList())); + return raw.stream().map(i -> i.parse ? parse(i.arg) : i.arg).collect(Collectors.joining(" ")); } public List asList() {