diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 8039cc54e..7345bb5de 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -45,6 +45,7 @@ import org.jackhuang.hmcl.util.platform.SystemInfo; import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; import java.net.CookieHandler; import java.net.CookieManager; import java.nio.file.Files; @@ -55,6 +56,7 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; +import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES; import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -247,13 +249,17 @@ public final class Launcher extends Application { LOG.info("HMCL Current Directory: " + Metadata.HMCL_CURRENT_DIRECTORY); LOG.info("HMCL Jar Path: " + Lang.requireNonNullElse(JarUtils.thisJarPath(), "Not Found")); LOG.info("HMCL Log File: " + Lang.requireNonNullElse(LOG.getLogFile(), "In Memory")); - LOG.info("Memory: " + Runtime.getRuntime().maxMemory() / 1024 / 1024 + "MB"); - LOG.info("Physical Memory: " + OperatingSystem.TOTAL_MEMORY + " MB"); - LOG.info("Metaspace: " + ManagementFactory.getMemoryPoolMXBeans().stream() - .filter(bean -> bean.getName().equals("Metaspace")) - .findAny() - .map(bean -> bean.getUsage().getUsed() / 1024 / 1024 + "MB") - .orElse("Unknown")); + LOG.info("JVM Max Memory: " + MEGABYTES.formatBytes(Runtime.getRuntime().maxMemory())); + try { + for (MemoryPoolMXBean bean : ManagementFactory.getMemoryPoolMXBeans()) { + if ("Metaspace".equals(bean.getName())) { + long bytes = bean.getUsage().getUsed(); + LOG.info("Metaspace: " + MEGABYTES.formatBytes(bytes)); + break; + } + } + } catch (NoClassDefFoundError ignored) { + } LOG.info("Native Backend: " + (NativeUtils.USE_JNA ? "JNA" : "None")); if (OperatingSystem.CURRENT_OS.isLinuxOrBSD()) { LOG.info("XDG Session Type: " + System.getenv("XDG_SESSION_TYPE")); 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 423cc45d2..baa4e3290 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -40,6 +40,7 @@ import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.java.JavaRuntime; import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jackhuang.hmcl.util.platform.SystemInfo; import org.jackhuang.hmcl.util.versioning.VersionNumber; import org.jetbrains.annotations.Nullable; @@ -383,7 +384,7 @@ public class HMCLGameRepository extends DefaultGameRepository { .setOverrideJavaArguments(StringUtils.tokenize(vs.getJavaArgs())) .setMaxMemory(vs.isNoJVMArgs() && vs.isAutoMemory() ? null : (int)(getAllocatedMemory( vs.getMaxMemory() * 1024L * 1024L, - OperatingSystem.getPhysicalMemoryStatus().getAvailable(), + SystemInfo.getPhysicalMemoryStatus().getAvailable(), vs.isAutoMemory() ) / 1024 / 1024)) .setMinMemory(vs.getMinMemory()) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java index 216aff254..583ece830 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/LauncherHelper.java @@ -63,6 +63,7 @@ import java.util.stream.Collectors; import static javafx.application.Platform.runLater; import static javafx.application.Platform.setImplicitExit; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; +import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES; import static org.jackhuang.hmcl.util.Lang.resolveException; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.logging.Logger.LOG; @@ -553,8 +554,9 @@ public final class LauncherHelper { } // Cannot allocate too much memory exceeding free space. - if (OperatingSystem.TOTAL_MEMORY > 0 && OperatingSystem.TOTAL_MEMORY < setting.getMaxMemory()) { - suggestions.add(i18n("launch.advice.not_enough_space", OperatingSystem.TOTAL_MEMORY)); + long totalMemorySizeMB = (long) MEGABYTES.convertFromBytes(SystemInfo.getTotalMemorySize()); + if (totalMemorySizeMB > 0 && totalMemorySizeMB < setting.getMaxMemory()) { + suggestions.add(i18n("launch.advice.not_enough_space", totalMemorySizeMB)); } VersionNumber forgeVersion = analyzer.getVersion(LibraryAnalyzer.LibraryType.FORGE) 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 39fb1afd4..d08ca405b 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/VersionSetting.java @@ -29,7 +29,7 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.javafx.ObservableHelper; import org.jackhuang.hmcl.util.javafx.PropertyUtils; import org.jackhuang.hmcl.java.JavaRuntime; -import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jackhuang.hmcl.util.platform.SystemInfo; import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.io.IOException; @@ -39,6 +39,7 @@ import java.nio.file.Paths; import java.util.*; import java.util.stream.Collectors; +import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES; import static org.jackhuang.hmcl.util.logging.Logger.LOG; /** @@ -47,7 +48,16 @@ import static org.jackhuang.hmcl.util.logging.Logger.LOG; @JsonAdapter(VersionSetting.Serializer.class) public final class VersionSetting implements Cloneable, Observable { - private transient ObservableHelper helper = new ObservableHelper(this); + private static final int SUGGESTED_MEMORY; + + static { + double totalMemoryMB = MEGABYTES.convertFromBytes(SystemInfo.getTotalMemorySize()); + SUGGESTED_MEMORY = totalMemoryMB >= 32768 + ? 8192 + : Integer.max((int) (Math.round(totalMemoryMB / 4.0 / 128.0) * 128), 256); + } + + private final transient ObservableHelper helper = new ObservableHelper(this); public VersionSetting() { PropertyUtils.attachListener(this, helper); @@ -219,7 +229,7 @@ public final class VersionSetting implements Cloneable, Observable { permSizeProperty.set(permSize); } - private final IntegerProperty maxMemoryProperty = new SimpleIntegerProperty(this, "maxMemory", OperatingSystem.SUGGESTED_MEMORY); + private final IntegerProperty maxMemoryProperty = new SimpleIntegerProperty(this, "maxMemory", SUGGESTED_MEMORY); public IntegerProperty maxMemoryProperty() { return maxMemoryProperty; @@ -734,7 +744,7 @@ public final class VersionSetting implements Cloneable, Observable { obj.addProperty("javaArgs", src.getJavaArgs()); obj.addProperty("minecraftArgs", src.getMinecraftArgs()); obj.addProperty("environmentVariables", src.getEnvironmentVariables()); - obj.addProperty("maxMemory", src.getMaxMemory() <= 0 ? OperatingSystem.SUGGESTED_MEMORY : src.getMaxMemory()); + obj.addProperty("maxMemory", src.getMaxMemory() <= 0 ? SUGGESTED_MEMORY : src.getMaxMemory()); obj.addProperty("minMemory", src.getMinMemory()); obj.addProperty("autoMemory", src.isAutoMemory()); obj.addProperty("permSize", src.getPermSize()); @@ -801,8 +811,8 @@ public final class VersionSetting implements Cloneable, Observable { return null; JsonObject obj = (JsonObject) json; - int maxMemoryN = parseJsonPrimitive(Optional.ofNullable(obj.get("maxMemory")).map(JsonElement::getAsJsonPrimitive).orElse(null), OperatingSystem.SUGGESTED_MEMORY); - if (maxMemoryN <= 0) maxMemoryN = OperatingSystem.SUGGESTED_MEMORY; + int maxMemoryN = parseJsonPrimitive(Optional.ofNullable(obj.get("maxMemory")).map(JsonElement::getAsJsonPrimitive).orElse(null), SUGGESTED_MEMORY); + if (maxMemoryN <= 0) maxMemoryN = SUGGESTED_MEMORY; VersionSetting vs = new VersionSetting(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java index 4e815882c..df036b80c 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/GameCrashWindow.java @@ -41,16 +41,10 @@ import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Task; import org.jackhuang.hmcl.ui.construct.TwoLineListItem; -import org.jackhuang.hmcl.util.Lang; -import org.jackhuang.hmcl.util.Log4jLevel; +import org.jackhuang.hmcl.util.*; import org.jackhuang.hmcl.util.logging.Logger; -import org.jackhuang.hmcl.util.Pair; -import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.FileUtils; -import org.jackhuang.hmcl.util.platform.Architecture; -import org.jackhuang.hmcl.util.platform.CommandBuilder; -import org.jackhuang.hmcl.util.platform.ManagedProcess; -import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jackhuang.hmcl.util.platform.*; import java.io.IOException; import java.nio.file.Files; @@ -65,6 +59,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.jackhuang.hmcl.setting.ConfigHolder.config; +import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES; import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.Pair.pair; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -98,7 +93,7 @@ public class GameCrashWindow extends Stage { memory = Optional.ofNullable(launchOptions.getMaxMemory()).map(i -> i + " MB").orElse("-"); - total_memory = OperatingSystem.TOTAL_MEMORY + " MB"; + total_memory = MEGABYTES.formatBytes(SystemInfo.getTotalMemorySize()); this.java = launchOptions.getJava().getArchitecture() == Architecture.SYSTEM_ARCH ? launchOptions.getJava().getVersion() diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java index 4ce0b9be0..36191ba05 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java @@ -98,17 +98,15 @@ public class TaskExecutorDialogPane extends BorderPane { double speed = speedEvent.getSpeed(); if (speed > 1024) { speed /= 1024; - unit = "KB/s"; + unit = "KiB/s"; } if (speed > 1024) { speed /= 1024; - unit = "MB/s"; + unit = "MiB/s"; } double finalSpeed = speed; String finalUnit = unit; - Platform.runLater(() -> { - lblProgress.setText(String.format("%.1f %s", finalSpeed, finalUnit)); - }); + Platform.runLater(() -> lblProgress.setText(String.format("%.1f %s", finalSpeed, finalUnit))); }; FileDownloadTask.speedEvent.channel(FileDownloadTask.SpeedEvent.class).registerWeak(speedEventHandler); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java index 29198fd6d..94d4742db 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java @@ -43,7 +43,7 @@ import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.JarUtils; -import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jackhuang.hmcl.util.platform.SystemInfo; import java.io.File; import java.util.*; @@ -54,6 +54,7 @@ import static org.jackhuang.hmcl.ui.FXUtils.jfxListCellFactory; import static org.jackhuang.hmcl.ui.FXUtils.stringConverter; import static org.jackhuang.hmcl.ui.export.ModpackTypeSelectionPage.MODPACK_TYPE; import static org.jackhuang.hmcl.ui.export.ModpackTypeSelectionPage.MODPACK_TYPE_SERVER; +import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES; import static org.jackhuang.hmcl.util.Lang.tryCast; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -287,12 +288,12 @@ public final class ModpackInfoPage extends Control implements WizardPage { AtomicBoolean changedByTextField = new AtomicBoolean(false); FXUtils.onChangeAndOperate(skinnable.minMemory, minMemory -> { changedByTextField.set(true); - slider.setValue(minMemory.intValue() * 1.0 / OperatingSystem.TOTAL_MEMORY); + slider.setValue(minMemory.intValue() * 1.0 / MEGABYTES.convertFromBytes(SystemInfo.getTotalMemorySize())); changedByTextField.set(false); }); slider.valueProperty().addListener((value, oldVal, newVal) -> { if (changedByTextField.get()) return; - skinnable.minMemory.set((int) (value.getValue().doubleValue() * OperatingSystem.TOTAL_MEMORY)); + skinnable.minMemory.set((int) (value.getValue().doubleValue() * MEGABYTES.convertFromBytes(SystemInfo.getTotalMemorySize()))); }); JFXTextField txtMinMemory = new JFXTextField(); @@ -301,7 +302,7 @@ public final class ModpackInfoPage extends Control implements WizardPage { FXUtils.setLimitWidth(txtMinMemory, 60); validatingFields.add(txtMinMemory); - lowerBoundPane.getChildren().setAll(label, slider, txtMinMemory, new Label("MB")); + lowerBoundPane.getChildren().setAll(label, slider, txtMinMemory, new Label("MiB")); } pane.getChildren().setAll(title, lowerBoundPane); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java index 62dfe743f..c2675a7df 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/versions/VersionSettingsPage.java @@ -51,6 +51,8 @@ import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.java.JavaRuntime; import org.jackhuang.hmcl.util.platform.OperatingSystem; +import org.jackhuang.hmcl.util.platform.SystemInfo; +import org.jackhuang.hmcl.util.platform.hardware.PhysicalMemoryStatus; import org.jackhuang.hmcl.util.versioning.GameVersionNumber; import java.nio.file.Paths; @@ -58,13 +60,15 @@ import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import static org.jackhuang.hmcl.ui.FXUtils.stringConverter; +import static org.jackhuang.hmcl.util.DataSizeUnit.GIGABYTES; +import static org.jackhuang.hmcl.util.DataSizeUnit.MEGABYTES; import static org.jackhuang.hmcl.util.Lang.getTimer; import static org.jackhuang.hmcl.util.Pair.pair; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public final class VersionSettingsPage extends StackPane implements DecoratorPage, VersionPage.VersionLoadable, PageAware { - private static final ObjectProperty memoryStatus = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID); + private static final ObjectProperty memoryStatus = new SimpleObjectProperty<>(PhysicalMemoryStatus.INVALID); private static TimerTask memoryStatusUpdateTask; private static void initMemoryStatusUpdateTask() { @@ -74,7 +78,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag memoryStatusUpdateTask = new TimerTask() { @Override public void run() { - Platform.runLater(() -> memoryStatus.set(OperatingSystem.getPhysicalMemoryStatus())); + Platform.runLater(() -> memoryStatus.set(SystemInfo.getPhysicalMemoryStatus())); } }; getTimer().scheduleAtFixedRate(memoryStatusUpdateTask, 0, 1000); @@ -295,12 +299,12 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag AtomicBoolean changedByTextField = new AtomicBoolean(false); FXUtils.onChangeAndOperate(maxMemory, maxMemory -> { changedByTextField.set(true); - slider.setValue(maxMemory.intValue() * 1.0 / OperatingSystem.TOTAL_MEMORY); + slider.setValue(maxMemory.intValue() * 1.0 / MEGABYTES.convertFromBytes(SystemInfo.getTotalMemorySize())); changedByTextField.set(false); }); slider.valueProperty().addListener((value, oldVal, newVal) -> { if (changedByTextField.get()) return; - maxMemory.set((int) (value.getValue().doubleValue() * OperatingSystem.TOTAL_MEMORY)); + maxMemory.set((int) (value.getValue().doubleValue() * MEGABYTES.convertFromBytes(SystemInfo.getTotalMemorySize()))); }); JFXTextField txtMaxMemory = new JFXTextField(); @@ -309,7 +313,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag txtMaxMemory.textProperty().bindBidirectional(maxMemory, SafeStringConverter.fromInteger()); txtMaxMemory.setValidators(new NumberValidator(i18n("input.number"), false)); - lowerBoundPane.getChildren().setAll(label, slider, txtMaxMemory, new Label("MB")); + lowerBoundPane.getChildren().setAll(label, slider, txtMaxMemory, new Label("MiB")); } StackPane progressBarPane = new StackPane(); @@ -343,9 +347,10 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag Label lblPhysicalMemory = new Label(); lblPhysicalMemory.getStyleClass().add("memory-label"); digitalPane.setLeft(lblPhysicalMemory); - lblPhysicalMemory.textProperty().bind(Bindings.createStringBinding(() -> { - return i18n("settings.memory.used_per_total", memoryStatus.get().getUsedGB(), memoryStatus.get().getTotalGB()); - }, memoryStatus)); + lblPhysicalMemory.textProperty().bind(Bindings.createStringBinding(() -> + i18n("settings.memory.used_per_total", + GIGABYTES.convertFromBytes(memoryStatus.get().getUsed()), + GIGABYTES.convertFromBytes(memoryStatus.get().getTotal())), memoryStatus)); Label lblAllocateMemory = new Label(); lblAllocateMemory.textProperty().bind(Bindings.createStringBinding(() -> { @@ -353,9 +358,9 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag return i18n(memoryStatus.get().hasAvailable() && maxMemory > memoryStatus.get().getAvailable() ? (chkAutoAllocate.isSelected() ? "settings.memory.allocate.auto.exceeded" : "settings.memory.allocate.manual.exceeded") : (chkAutoAllocate.isSelected() ? "settings.memory.allocate.auto" : "settings.memory.allocate.manual"), - OperatingSystem.PhysicalMemoryStatus.toGigaBytes(maxMemory), - OperatingSystem.PhysicalMemoryStatus.toGigaBytes(HMCLGameRepository.getAllocatedMemory(maxMemory, memoryStatus.get().getAvailable(), chkAutoAllocate.isSelected())), - OperatingSystem.PhysicalMemoryStatus.toGigaBytes(memoryStatus.get().getAvailable())); + GIGABYTES.convertFromBytes(maxMemory), + GIGABYTES.convertFromBytes(HMCLGameRepository.getAllocatedMemory(maxMemory, memoryStatus.get().getAvailable(), chkAutoAllocate.isSelected())), + GIGABYTES.convertFromBytes(memoryStatus.get().getAvailable())); }, memoryStatus, maxMemory, chkAutoAllocate.selectedProperty())); lblAllocateMemory.getStyleClass().add("memory-label"); digitalPane.setRight(lblAllocateMemory); @@ -507,7 +512,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag cboProcessPriority.getItems().setAll(ProcessPriority.values()); cboProcessPriority.setConverter(stringConverter(e -> i18n("settings.advanced.process_priority." + e.name().toLowerCase(Locale.ROOT)))); - memoryStatus.set(OperatingSystem.getPhysicalMemoryStatus()); + memoryStatus.set(SystemInfo.getPhysicalMemoryStatus()); componentList.disableProperty().bind(enableSpecificSettings.not()); initMemoryStatusUpdateTask(); diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index c5ca87494..0eb8cc156 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -552,7 +552,7 @@ game.crash.reason.jvm_32bit=The game crashed because the current memory allocati \n\ If your OS is 64-bit, please install and use a 64-bit Java version. Otherwise, you may need to reinstall a 64-bit OS or get a moderner computer.\n\ \n\ - Or, you can disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory" and set the maximum memory allocation size to 1024 MB or below. + Or, you can disable the "Automatically Allocate" option in "Global/Instance-specific Settings → Memory" and set the maximum memory allocation size to 1024 MiB or below. game.crash.reason.loading_crashed_forge=The game crashed because of the mod "%1$s" (%2$s).\n\ \n\ You can try deleting or updating it. @@ -762,7 +762,7 @@ launch.advice.java9=You cannot launch Minecraft 1.12 or earlier with Java 9 or l launch.advice.modded_java=Some mods may not be compatible with newer Java versions. It is recommended to use Java %s to launch Minecraft %s. launch.advice.modlauncher8=The Forge version you are using is not compatible with the current Java version. Please try updating Forge. launch.advice.newer_java=You are using an older Java version to launch the game. It is recommended to update to Java 8, otherwise some mods may cause the game to crash. -launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MB of memory installed on your computer. You may experience degraded performance or even be unable to launch the game. +launch.advice.not_enough_space=You have allocated a memory size larger than the actual %d MiB of memory installed on your computer. You may experience degraded performance or even be unable to launch the game. launch.advice.require_newer_java_version=The current game version requires Java %s, but we could not find one. Do you want to download one now? launch.advice.too_large_memory_for_32bit=You have allocated a memory size larger than the memory limitation of the 32-bit Java installation. You may be unable to launch the game. launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 or earlier only supports Java 8 for the Linux x86-64 platform because the later versions cannot load 32-bit native libraries like liblwjgl.so\n\nPlease download it from java.com or install OpenJDK 8. @@ -1177,7 +1177,7 @@ settings.advanced.environment_variables=Environment Variables settings.advanced.game_dir.default=Default (".minecraft/") settings.advanced.game_dir.independent=Isolated (".minecraft/versions//", except for assets and libraries) settings.advanced.java_permanent_generation_space=PermGen Space -settings.advanced.java_permanent_generation_space.prompt=in MB +settings.advanced.java_permanent_generation_space.prompt=in MiB settings.advanced.jvm=Java VM Options settings.advanced.jvm_args=Java VM Arguments settings.advanced.jvm_args.prompt=\ · If the arguments entered in "Java VM arguments" are the same as the default arguments, it will not be added.\n\ @@ -1287,13 +1287,13 @@ settings.launcher.turn_off_animations=Disable Animation (Applies After Restart) settings.launcher.version_list_source=Version List settings.memory=Memory -settings.memory.allocate.auto=%1$.1f GB Minimum / %2$.1f GB Allocated -settings.memory.allocate.auto.exceeded=%1$.1f GB Minimum / %2$.1f GB Allocated (%3$.1f GB Available) -settings.memory.allocate.manual=%1$.1f GB Allocated -settings.memory.allocate.manual.exceeded=%1$.1f GB Allocated (%3$.1f GB Available) +settings.memory.allocate.auto=%1$.1f GiB Minimum / %2$.1f GiB Allocated +settings.memory.allocate.auto.exceeded=%1$.1f GiB Minimum / %2$.1f GiB Allocated (%3$.1f GiB Available) +settings.memory.allocate.manual=%1$.1f GiB Allocated +settings.memory.allocate.manual.exceeded=%1$.1f GiB Allocated (%3$.1f GiB Available) settings.memory.auto_allocate=Automatically Allocate settings.memory.lower_bound=Minimum Memory -settings.memory.used_per_total=%1$.1f GB Used / %2$.1f GB Total +settings.memory.used_per_total=%1$.1f GiB Used / %2$.1f GiB Total settings.physical_memory=Physical Memory Size settings.show_log=Show Logs settings.tabs.installers=Loaders diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 28cf98ffa..50f80a245 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -500,7 +500,7 @@ game.crash.reason.jvm_32bit=El juego se ha colgado porque la asignación de memo \n\ Si su sistema operativo es de 64 bits, instale y utilice una versión de Java de 64 bits. De lo contrario, es posible que tenga que volver a instalar un sistema operativo de 64 bits o adquirir un ordenador más moderno.\n\ \n\ - O bien, puede desactivar la opción «Asignar automáticamente» en «Config. Global/Específica de instancia → Memoria» y establecer el tamaño máximo de asignación de memoria en 1024 MB o menos. + O bien, puede desactivar la opción «Asignar automáticamente» en «Config. Global/Específica de instancia → Memoria» y establecer el tamaño máximo de asignación de memoria en 1024 MiB o menos. game.crash.reason.loading_crashed_forge=El juego se ha colgado debido al mod «%1$s» (%2$s).\n\ \n\ Puedes intentar borrarlo o actualizarlo. @@ -767,7 +767,7 @@ launch.advice.java9=No puedes ejecutar Minecraft 1.12 o anterior con Java 9 o m launch.advice.modded_java=Algunos mods pueden no ser compatibles con las nuevas versiones de Java. Se recomienda utilizar Java %s para iniciar Minecraft %s. launch.advice.modlauncher8=La versión de Forge que estás utilizando no es compatible con la versión actual de Java. Por favor, intenta actualizar Forge. launch.advice.newer_java=Estás utilizando una versión antigua de Java para iniciar el juego. Se recomienda actualizar a Java 8, de lo contrario algunos mods pueden hacer que el juego se bloquee. -launch.advice.not_enough_space=Has asignado un tamaño de memoria mayor que los %d MB reales de memoria instalados en tu máquina. Es posible que el rendimiento del juego se vea afectado, o incluso que no puedas iniciar el juego. +launch.advice.not_enough_space=Has asignado un tamaño de memoria mayor que los %d MiB reales de memoria instalados en tu máquina. Es posible que el rendimiento del juego se vea afectado, o incluso que no puedas iniciar el juego. launch.advice.require_newer_java_version=La versión actual del juego requiere Java %s, pero no hemos podido encontrar uno. ¿Quieres descargar uno ahora? launch.advice.too_large_memory_for_32bit=Has asignado un tamaño de memoria mayor que la limitación de memoria de la instalación de Java de 32 bits. Es posible que no puedas iniciar el juego. launch.advice.vanilla_linux_java_8=Minecraft 1.12.2 o inferior sólo admite Java 8 para la plataforma Linux x86-64, porque las versiones posteriores no pueden cargar las bibliotecas nativas de 32 bits como liblwjgl.so\n\nPor favor, descárguelo de java.com, o instale OpenJDK 8. @@ -1182,7 +1182,7 @@ settings.advanced.environment_variables=Variables de entorno settings.advanced.game_dir.default=Por defecto («.minecraft/») settings.advanced.game_dir.independent=Aislar («.minecraft/versions//», excepto para los activos y las bibliotecas) settings.advanced.java_permanent_generation_space=Espacio PermGen -settings.advanced.java_permanent_generation_space.prompt=en MB +settings.advanced.java_permanent_generation_space.prompt=en MiB settings.advanced.jvm=Opciones de la máquina virtual de Java settings.advanced.jvm_args=Argumentos de la máquina virtual de Java settings.advanced.jvm_args.prompt=\ · Si los argumentos introducidos en «Argumentos de la máquina virtual de Java» son los mismos que los argumentos por defecto, no se añadirán.\n\ @@ -1291,13 +1291,13 @@ settings.launcher.turn_off_animations=Desactivar animación (Se aplica después settings.launcher.version_list_source=Lista de versiones settings.memory=Memoria -settings.memory.allocate.auto=%1$.1f GB Mínimo / %2$.1f GB Asignado -settings.memory.allocate.auto.exceeded=%1$.1f GB Mínimo / %2$.1f GB Asignado (%3$.1f GB Disponible) -settings.memory.allocate.manual=%1$.1f GB Asignados -settings.memory.allocate.manual.exceeded=%1$.1f GB Asignados (%3$.1f GB Disponibles) +settings.memory.allocate.auto=%1$.1f GiB Mínimo / %2$.1f GiB Asignado +settings.memory.allocate.auto.exceeded=%1$.1f GiB Mínimo / %2$.1f GiB Asignado (%3$.1f GiB Disponible) +settings.memory.allocate.manual=%1$.1f GiB Asignados +settings.memory.allocate.manual.exceeded=%1$.1f GiB Asignados (%3$.1f GiB Disponibles) settings.memory.auto_allocate=Asignar automáticamente settings.memory.lower_bound=Memoria mínima -settings.memory.used_per_total=%1$.1f GB Utilizados / %2$.1f GB Totales +settings.memory.used_per_total=%1$.1f GiB Utilizados / %2$.1f GiB Totales settings.physical_memory=Tamaño de la memoria física settings.show_log=Mostrar registros settings.tabs.installers=Cargadores diff --git a/HMCL/src/main/resources/assets/lang/I18N_ja.properties b/HMCL/src/main/resources/assets/lang/I18N_ja.properties index 6725e018e..9d2b318af 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ja.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ja.properties @@ -379,7 +379,7 @@ game.crash.reason.macos_failed_to_find_service_port_for_display=現在のゲー game.crash.reason.illegal_access_error=一部のmodが原因でゲームがクラッシュしました。\n認識している場合:%1$s、modを更新または削除して、再試行してください。 game.crash.reason.install_mixinbootstrap=MixinBootstrapが見つからないため、現在のゲームを続行できません。\nMixinBootstrapをインストールしてみてください。インストール後にクラッシュする場合は、モジュールのファイル名の前に英語の「! をモジュールのファイル名の前につけてみてください。 game.crash.reason.jdk_9=Javaのバージョンが高すぎるため、ゲームを実行できません。\nJava 8をダウンロードしてインストールし、ゲーム設定で新しくインストールしたJavaを選択する必要があります。 -game.crash.reason.jvm_32bit=メモリ割り当てが32ビットJavaVMの制限を超えたため、ゲームがクラッシュしました。\nOSが64ビットの場合は、64ビットJavaをインストールして使用してください。OSが32ビットの場合は、64ビットOSを再インストールするか、新しいコンピュータを変更できます。\nまたは、自動メモリ割り当てを無効にして、最大メモリサイズを1024MB以下に設定できます。 +game.crash.reason.jvm_32bit=メモリ割り当てが32ビットJavaVMの制限を超えたため、ゲームがクラッシュしました。\nOSが64ビットの場合は、64ビットJavaをインストールして使用してください。OSが32ビットの場合は、64ビットOSを再インストールするか、新しいコンピュータを変更できます。\nまたは、自動メモリ割り当てを無効にして、最大メモリサイズを1024MiB以下に設定できます。 game.crash.reason.loading_crashed_forge=mod %1$s(%2$s)がクラッシュしたため、ゲームがクラッシュしました。\n削除または更新を試みることができます。 game.crash.reason.loading_crashed_fabric=mod %1$s がクラッシュしたため、ゲームがクラッシュしました。\n削除または更新を試みることができます。 game.crash.reason.memory_exceeded=JVMが割り当てるのに十分なメモリがないため、ゲームがクラッシュしました。\nこの問題は、ページサイズが小さすぎることが原因です。\nゲーム設定で自動メモリ割り当てをオフにし、メモリ割り当てを次のように調整する必要があります。システムが処理できる値。\nシステムのページサイズを十分な大きさに調整することもできます。 @@ -506,8 +506,8 @@ launch.advice.java8_1_13=Minecraft 1.13以降は、Java8以降でのみ実行で launch.advice.java8_51_1_13=Minecraft 1.13は、1.8.0_51より前のJava8でクラッシュする可能性があります。最新バージョンのJava8をインストールしてください。 launch.advice.java9=Java9以降のバージョンのJavaでMinecraft1.12以前を起動することはできません。ゲームを高速化するには、Java8をお勧めします。 launch.advice.newer_java=多くのMinecraft1.12以降、およびほとんどのModには、Java8が必要です。 -launch.advice.not_enough_space=割り当てたメモリが多すぎます。物理メモリサイズが%dMBであるため、ゲームがクラッシュする可能性があります。 -launch.advice.too_large_memory_for_32bit=32ビットJavaランタイム環境が原因で、割り当てたメモリが多すぎるため、ゲームがクラッシュする可能性があります。32ビットシステムの最大メモリ容量は1024MBです。 +launch.advice.not_enough_space=割り当てたメモリが多すぎます。物理メモリサイズが%dMiBであるため、ゲームがクラッシュする可能性があります。 +launch.advice.too_large_memory_for_32bit=32ビットJavaランタイム環境が原因で、割り当てたメモリが多すぎるため、ゲームがクラッシュする可能性があります。32ビットシステムの最大メモリ容量は1024MiBです。 launch.advice.vanilla_linux_java_8=Linux x86-64の場合、Minecraft1.12.2以下はJava8でのみ実行できます。\nJava9以降のバージョンでは、liblwjgl.soなどの32ビットネイティブライブラリをロードできません。 launch.advice.vanilla_x86.translation=Minecraftは現在、x86およびx86-64以外のアーキテクチャの公式サポートを提供していません。\nJava for x86-64を使用して、トランスレータを介してminecraftを実行するか、プラットフォームの対応するネイティブライブラリをダウンロードして指定してくださいその配置パス。 launch.failed=起動できません @@ -772,8 +772,8 @@ settings.advanced.dont_check_game_completeness=ゲームファイルをスキャ settings.advanced.dont_check_jvm_validity=JVMがゲームを起動できるかどうかを確認しないでください settings.advanced.game_dir.default=標準(.minecraft /) settings.advanced.game_dir.independent=バージョン独立(.minecraft / versions / <バージョン名> /、アセットとライブラリを除く) -settings.advanced.java_permanent_generation_space=PermGen Space / MB -settings.advanced.java_permanent_generation_space.prompt=Java 8以降のメタスペース、MB +settings.advanced.java_permanent_generation_space=PermGen Space / MiB +settings.advanced.java_permanent_generation_space.prompt=Java 8以降のメタスペース、MiB settings.advanced.jvm=Java仮想マシンの設定 settings.advanced.jvm_args=JavaVM引数 settings.advanced.jvm_args.prompt=- 入力パラメータがデフォルトパラメータと同じである場合、追加されません\n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 137fcca2a..c454e39b3 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -435,7 +435,7 @@ game.crash.reason.macos_failed_to_find_service_port_for_display=目前遊戲由 game.crash.reason.illegal_access_error=目前遊戲由於某些模組的問題,無法繼續執行。\n如果你認識「%1$s」,你可以更新或刪除對應模組再試。 game.crash.reason.install_mixinbootstrap=目前遊戲由於缺失 MixinBootstrap,無法繼續執行。\n你可以嘗試安裝 MixinBootstrap 解決該問題。若安裝後崩潰,嘗試在該模組的檔案名前加入半形驚嘆號 (!) 嘗試解決。 game.crash.reason.jdk_9=目前遊戲由於 Java 版本過高,無法繼續執行。\n你需要下載安裝 Java 8,並在「(全域/實例特定) 遊戲設定 → 遊戲 Java」中將 Java 設定為 1.8 的版本。 -game.crash.reason.jvm_32bit=目前遊戲由於記憶體分配過大,超過了 32 位 Java 記憶體限制,無法繼續執行。\n如果你的電腦是 64 位系統,請下載安裝並更換 64 位 Java。\n如果你的電腦是 32 位系統,你或許可以重新安裝 64 位系統,或換一台新電腦。\n或者,你可以關閉「(全域/實例特定) 遊戲設定 → 遊戲記憶體」中的「自動分配」,並且把記憶體限制調節為 1024 MB 或以下。 +game.crash.reason.jvm_32bit=目前遊戲由於記憶體分配過大,超過了 32 位 Java 記憶體限制,無法繼續執行。\n如果你的電腦是 64 位系統,請下載安裝並更換 64 位 Java。\n如果你的電腦是 32 位系統,你或許可以重新安裝 64 位系統,或換一台新電腦。\n或者,你可以關閉「(全域/實例特定) 遊戲設定 → 遊戲記憶體」中的「自動分配」,並且把記憶體限制調節為 1024 MiB 或以下。 game.crash.reason.loading_crashed_forge=目前遊戲由於模組「%1$s (%2$s)」錯誤,無法繼續執行。\n你可以嘗試刪除或更新該模組以解決問題。 game.crash.reason.loading_crashed_fabric=目前遊戲由於模組「%1$s」錯誤,無法繼續執行。\n你可以嘗試刪除或更新該模組以解決問題。 game.crash.reason.mac_jdk_8u261=目前遊戲由於你所使用的 Forge 或 OptiFine 與 Java 衝突而崩潰。\n請嘗試更新 Forge 和 OptiFine,或使用 Java 8u251 及更早版本啟動。 @@ -578,9 +578,9 @@ launch.advice.java9=低於 (包含) 1.13 的有安裝模組的 Minecraft 版本 launch.advice.modded_java=部分模組可能與高版本 Java 不相容,建議使用 Java %s 啟動 Minecraft %s。 launch.advice.modlauncher8=你所使用的 Forge 版本與目前使用的 Java 不相容。請更新 Forge。 launch.advice.newer_java=偵測到你正在使用舊版本 Java 啟動遊戲,這可能導致部分模組引發遊戲崩潰,建議更新至 Java 8 後再次啟動。 -launch.advice.not_enough_space=你設定的記憶體大小過大,由於超過了系統記憶體大小 %d MB,所以可能影響遊戲體驗或無法啟動遊戲。 +launch.advice.not_enough_space=你設定的記憶體大小過大,由於超過了系統記憶體大小 %d MiB,所以可能影響遊戲體驗或無法啟動遊戲。 launch.advice.require_newer_java_version=目前遊戲版本需要 Java %s,但 HMCL 未能找到該 Java 版本,你可以點擊「是」,HMCL 會自動下載他,是否下載? -launch.advice.too_large_memory_for_32bit=你設定的記憶體大小過大,由於可能超過了 32 位元 Java 的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至低於 1024 MB 的值。 +launch.advice.too_large_memory_for_32bit=你設定的記憶體大小過大,由於可能超過了 32 位元 Java 的記憶體分配限制,所以可能無法啟動遊戲,請將記憶體調至低於 1024 MiB 的值。 launch.advice.vanilla_linux_java_8=對於 Linux x86-64 平台,Minecraft 1.12.2 及更低版本與 Java 9+ 不相容,請使用 Java 8 啟動遊戲。 launch.advice.vanilla_x86.translation=Minecraft 尚未為你的平臺提供完善支援,所以可能影響遊戲體驗或無法啟動遊戲。\n你可以在 這裡 下載 x86-64 架構的 Java 以獲得更完整的體驗。\n是否繼續啟動? launch.advice.unknown=由於以下原因,無法繼續啟動遊戲: @@ -978,7 +978,7 @@ settings.advanced.environment_variables=環境變數 settings.advanced.game_dir.default=預設 (".minecraft/") settings.advanced.game_dir.independent=各實例獨立 (".minecraft/versions/<實例名>/",除 assets、libraries 外) settings.advanced.java_permanent_generation_space=記憶體永久儲存區域 -settings.advanced.java_permanent_generation_space.prompt=單位 MB +settings.advanced.java_permanent_generation_space.prompt=單位 MiB settings.advanced.jvm=Java 虛擬機設定 settings.advanced.jvm_args=Java 虛擬機參數 settings.advanced.jvm_args.prompt=\ · 若在「Java 虛擬機參數」中輸入的參數與預設參數相同,則不會加入;\n\ @@ -1083,13 +1083,13 @@ settings.launcher.turn_off_animations=關閉動畫 (重啟後生效) settings.launcher.version_list_source=版本清單來源 settings.memory=遊戲記憶體 -settings.memory.allocate.auto=最低分配 %1$.1f GB / 實際分配 %2$.1f GB -settings.memory.allocate.auto.exceeded=最低分配 %1$.1f GB / 實際分配 %2$.1f GB (%3$.1f GB 可用) -settings.memory.allocate.manual=遊戲分配 %1$.1f GB -settings.memory.allocate.manual.exceeded=遊戲分配 %1$.1f GB (%3$.1f GB 可用) +settings.memory.allocate.auto=最低分配 %1$.1f GiB / 實際分配 %2$.1f GiB +settings.memory.allocate.auto.exceeded=最低分配 %1$.1f GiB / 實際分配 %2$.1f GiB (%3$.1f GiB 可用) +settings.memory.allocate.manual=遊戲分配 %1$.1f GiB +settings.memory.allocate.manual.exceeded=遊戲分配 %1$.1f GiB (%3$.1f GiB 可用) settings.memory.auto_allocate=自動分配 settings.memory.lower_bound=最低分配 -settings.memory.used_per_total=已使用 %1$.1f GB / 總記憶體 %2$.1f GB +settings.memory.used_per_total=已使用 %1$.1f GiB / 總記憶體 %2$.1f GiB settings.physical_memory=實體記憶體大小 settings.show_log=查看日誌 settings.tabs.installers=自動安裝 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 b8ae7141a..cd6a2ba29 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -439,7 +439,7 @@ game.crash.reason.illegal_access_error=当前游戏由于某些模组的问题 game.crash.reason.install_mixinbootstrap=当前游戏由于缺失 MixinBootstrap,无法继续运行。\n你可以尝试安装 MixinBootstrap 解决该问题。若安装后崩溃,尝试在该模组的文件名前加入半角感叹号 (!) 尝试解决。 game.crash.reason.need_jdk11=当前游戏由于 Java 虚拟机版本不合适,无法继续运行。\n你需要下载安装 Java 11,并在“(全局/版本特定) 游戏设置 → 游戏 Java”中将 Java 设置为 11 开头的版本。 game.crash.reason.jdk_9=当前游戏由于 Java 版本过高,无法继续运行。\n你需要下载安装 Java 8,并在“(全局/版本特定) 游戏设置 → 游戏 Java”中将 Java 设置为 1.8 的版本。 -game.crash.reason.jvm_32bit=当前游戏由于内存分配过大,超过了 32 位 Java 内存限制,无法继续运行。\n如果你的电脑是 64 位系统,请下载安装并更换 64 位 Java。下载 Java\n如果你的电脑是 32 位系统,你或许可以重新安装 64 位系统,或换一台新电脑。\n或者,你可以在“(全局/版本特定) 游戏设置 → 游戏内存”中关闭“自动分配内存”,并且把内存限制调节为 1024 MB 或以下。 +game.crash.reason.jvm_32bit=当前游戏由于内存分配过大,超过了 32 位 Java 内存限制,无法继续运行。\n如果你的电脑是 64 位系统,请下载安装并更换 64 位 Java。下载 Java\n如果你的电脑是 32 位系统,你或许可以重新安装 64 位系统,或换一台新电脑。\n或者,你可以在“(全局/版本特定) 游戏设置 → 游戏内存”中关闭“自动分配内存”,并且把内存限制调节为 1024 MiB 或以下。 game.crash.reason.loading_crashed_forge=当前游戏由于模组“%1$s (%2$s)”错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 game.crash.reason.loading_crashed_fabric=当前游戏由于模组“%1$s”错误,无法继续运行。\n你可以尝试删除或更新该模组以解决问题。 game.crash.reason.memory_exceeded=当前游戏由于分配的内存过大,无法继续运行。\n该问题是由于系统页面文件太小导致的。\n你需要在全局(特定)游戏设置中关闭游戏内存的自动分配,并将游戏内存调低至游戏能正常启动为止。\n你还可以尝试将虚拟内存设置调整为“自动管理所有驱动器分页文件大小”,详情。 @@ -588,9 +588,9 @@ launch.advice.java9=低于 1.13 的有安装模组的 Minecraft 版本与 Java 9 launch.advice.modded_java=部分模组可能与高版本 Java 不兼容,建议使用 Java %s 启动 Minecraft %s。 launch.advice.modlauncher8=你所使用的 Forge 版本与当前使用的 Java 不兼容,请更新 Forge。 launch.advice.newer_java=检测到你正在使用旧版本 Java 启动游戏,这可能导致部分模组引发游戏崩溃,建议更新至 Java 8 后再次启动。 -launch.advice.not_enough_space=你设置的内存大小过大,超过了系统内存容量 %d MB,可能导致游戏无法启动。 +launch.advice.not_enough_space=你设置的内存大小过大,超过了系统内存容量 %d MiB,可能导致游戏无法启动。 launch.advice.require_newer_java_version=当前游戏版本需要 Java %s,但 HMCL 未能找到该 Java 版本,你可以点击“是”,HMCL 会自动下载他,是否下载?\n如遇到问题,你可以点击右上角帮助按钮进行求助。 -launch.advice.too_large_memory_for_32bit=你设置的内存大小过大,由于可能超过了 32 位 Java 的内存分配限制,所以可能无法启动游戏,请将内存调至 1024 MB 或更小。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 +launch.advice.too_large_memory_for_32bit=你设置的内存大小过大,由于可能超过了 32 位 Java 的内存分配限制,所以可能无法启动游戏,请将内存调至 1024 MiB 或更小。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 launch.advice.vanilla_linux_java_8=对于 Linux x86-64 平台,Minecraft 1.12.2 及更低版本与 Java 9+ 不兼容,请使用 Java 8 启动游戏。\n如遇到问题,你可以点击右上角帮助按钮进行求助。 launch.advice.vanilla_x86.translation=Minecraft 尚未为你的平台提供完善支持,所以可能影响游戏体验或无法启动游戏。\n你可以在 这里 下载 x86-64 架构的 Java 以获得更完整的体验。 launch.advice.unknown=由于以下原因,无法继续启动游戏: @@ -988,7 +988,7 @@ settings.advanced.environment_variables=环境变量 settings.advanced.game_dir.default=默认 (".minecraft/") settings.advanced.game_dir.independent=各版本独立 (存放在 ".minecraft/versions/<版本名>/",除 assets、libraries 外) settings.advanced.java_permanent_generation_space=内存永久保存区域 -settings.advanced.java_permanent_generation_space.prompt=单位 MB +settings.advanced.java_permanent_generation_space.prompt=单位 MiB settings.advanced.jvm=Java 虚拟机设置 settings.advanced.jvm_args=Java 虚拟机参数 settings.advanced.jvm_args.prompt=\ · 若在“Java 虚拟机参数”输入的参数与默认参数相同,则不会添加;\n\ @@ -1093,13 +1093,13 @@ settings.launcher.turn_off_animations=关闭动画 (重启后生效) settings.launcher.version_list_source=版本列表源 settings.memory=游戏内存 -settings.memory.allocate.auto=最低分配 %1$.1f GB / 实际分配 %2$.1f GB -settings.memory.allocate.auto.exceeded=最低分配 %1$.1f GB / 实际分配 %2$.1f GB (%3$.1f GB 可用) -settings.memory.allocate.manual=游戏分配 %1$.1f GB -settings.memory.allocate.manual.exceeded=游戏分配 %1$.1f GB (设备仅 %3$.1f GB 可用) +settings.memory.allocate.auto=最低分配 %1$.1f GiB / 实际分配 %2$.1f GiB +settings.memory.allocate.auto.exceeded=最低分配 %1$.1f GiB / 实际分配 %2$.1f GiB (%3$.1f GiB 可用) +settings.memory.allocate.manual=游戏分配 %1$.1f GiB +settings.memory.allocate.manual.exceeded=游戏分配 %1$.1f GiB (设备仅 %3$.1f GiB 可用) settings.memory.auto_allocate=自动分配内存 settings.memory.lower_bound=最低内存分配 -settings.memory.used_per_total=设备中已使用 %1$.1f GB / 设备总内存 %2$.1f GB +settings.memory.used_per_total=设备中已使用 %1$.1f GiB / 设备总内存 %2$.1f GiB settings.physical_memory=物理内存大小 settings.show_log=查看日志 settings.tabs.installers=自动安装 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 22e42e3db..a2ad10ad8 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java @@ -212,7 +212,7 @@ public class DefaultLauncher extends Launcher { if (javaVersion <= 8) { res.addUnstableDefault("MaxInlineLevel", "15"); } - if (is64bit && OperatingSystem.TOTAL_MEMORY > 4 * 1024) { + if (is64bit && SystemInfo.getTotalMemorySize() > 4L * 1024 * 1024 * 1024) { res.addUnstableDefault("DontCompileHugeMethods", false); res.addUnstableDefault("MaxNodeLimit", "240000"); res.addUnstableDefault("NodeLimitFudgeFactor", "8000"); diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/DataSizeUnit.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/DataSizeUnit.java new file mode 100644 index 000000000..ee1e8e4e3 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/DataSizeUnit.java @@ -0,0 +1,66 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2025 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 java.text.DecimalFormat; + +/** + * @author Glavo + */ +public enum DataSizeUnit { + BYTES, + KILOBYTES, + MEGABYTES, + GIGABYTES, + TERABYTES; + + private static final DataSizeUnit[] VALUES = values(); + private static final DecimalFormat FORMAT = new DecimalFormat("#.##"); + + public static String format(long bytes) { + for (int i = VALUES.length - 1; i > 0; i--) { + DataSizeUnit unit = VALUES[i]; + if (bytes >= unit.bytes) { + return unit.formatBytes(bytes); + } + } + + return bytes == 1 ? "1 byte" : bytes + " bytes"; + } + + private final long bytes = 1L << (ordinal() * 10); + + private final char abbreviationChar = name().charAt(0); + private final String abbreviation = abbreviationChar == 'B' ? "B" : abbreviationChar + "iB"; + + public double convertFromBytes(long bytes) { + return (double) bytes / this.bytes; + } + + public long convertToBytes(double amount) { + return (long) (amount * this.bytes); + } + + private String format(double amount) { + return FORMAT.format(amount) + " " + this.abbreviation; + } + + public String formatBytes(long bytes) { + return format(convertFromBytes(bytes)); + } +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java index 94efbbcc4..b225598a9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java @@ -85,16 +85,6 @@ public enum OperatingSystem { */ public static final OperatingSystem CURRENT_OS = parseOSName(System.getProperty("os.name")); - /** - * The total memory/MB this computer have. - */ - public static final int TOTAL_MEMORY; - - /** - * The suggested memory size/MB for Minecraft to allocate. - */ - public static final int SUGGESTED_MEMORY; - public static final String PATH_SEPARATOR = File.pathSeparator; public static final String FILE_SEPARATOR = File.separator; public static final String LINE_SEPARATOR = System.lineSeparator(); @@ -129,8 +119,6 @@ public enum OperatingSystem { private static final String[] INVALID_RESOURCE_BASENAMES; private static final String[] INVALID_RESOURCE_FULLNAMES; - private static final Pattern MEMINFO_PATTERN = Pattern.compile("^(?.*?):\\s+(?\\d+) kB?$"); - static { String nativeEncoding = System.getProperty("native.encoding"); String hmclNativeEncoding = System.getProperty("hmcl.native.encoding"); @@ -246,13 +234,6 @@ public enum OperatingSystem { OS_RELEASE_NAME = osRelease.get("NAME"); OS_RELEASE_PRETTY_NAME = osRelease.get("PRETTY_NAME"); - PhysicalMemoryStatus physicalMemoryStatus = getPhysicalMemoryStatus(); - TOTAL_MEMORY = physicalMemoryStatus != PhysicalMemoryStatus.INVALID - ? (int) (physicalMemoryStatus.getTotal() / 1024 / 1024) - : 1024; - - SUGGESTED_MEMORY = TOTAL_MEMORY >= 32768 ? 8192 : (int) (Math.round(1.0 * TOTAL_MEMORY / 4.0 / 128.0) * 128); - // setup the invalid names if (CURRENT_OS == WINDOWS) { // valid names and characters taken from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp @@ -315,48 +296,6 @@ public enum OperatingSystem { return major >= 6 && !SYSTEM_VERSION.startsWith("6.0"); } - @SuppressWarnings("deprecation") - public static PhysicalMemoryStatus getPhysicalMemoryStatus() { - if (CURRENT_OS == LINUX) { - try { - long free = 0, available = 0, total = 0; - for (String line : Files.readAllLines(Paths.get("/proc/meminfo"))) { - Matcher matcher = MEMINFO_PATTERN.matcher(line); - if (matcher.find()) { - String key = matcher.group("key"); - String value = matcher.group("value"); - if ("MemAvailable".equals(key)) { - available = Long.parseLong(value) * 1024; - } - if ("MemFree".equals(key)) { - free = Long.parseLong(value) * 1024; - } - if ("MemTotal".equals(key)) { - total = Long.parseLong(value) * 1024; - } - } - } - if (total > 0) { - return new PhysicalMemoryStatus(total, available > 0 ? available : free); - } - } catch (IOException e) { - e.printStackTrace(System.err); - } - } - - try { - java.lang.management.OperatingSystemMXBean bean = java.lang.management.ManagementFactory.getOperatingSystemMXBean(); - if (bean instanceof com.sun.management.OperatingSystemMXBean) { - com.sun.management.OperatingSystemMXBean sunBean = - (com.sun.management.OperatingSystemMXBean) - java.lang.management.ManagementFactory.getOperatingSystemMXBean(); - return new PhysicalMemoryStatus(sunBean.getTotalPhysicalMemorySize(), sunBean.getFreePhysicalMemorySize()); - } - } catch (NoClassDefFoundError ignored) { - } - return PhysicalMemoryStatus.INVALID; - } - @SuppressWarnings("removal") public static void forceGC() { System.gc(); @@ -420,48 +359,4 @@ public enum OperatingSystem { return true; } - public static class PhysicalMemoryStatus { - private final long total; - private final long available; - - public PhysicalMemoryStatus(long total, long available) { - this.total = total; - this.available = available; - } - - public long getTotal() { - return total; - } - - public double getTotalGB() { - return toGigaBytes(total); - } - - public long getUsed() { - return hasAvailable() ? total - available : 0; - } - - public double getUsedGB() { - return toGigaBytes(getUsed()); - } - - public long getAvailable() { - return available; - } - - public double getAvailableGB() { - return toGigaBytes(available); - } - - public boolean hasAvailable() { - return available >= 0; - } - - public static double toGigaBytes(long bytes) { - return bytes / 1024. / 1024. / 1024.; - } - - public static final PhysicalMemoryStatus INVALID = new PhysicalMemoryStatus(0, -1); - } - } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemInfo.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemInfo.java index f0096e926..f716b9f9a 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemInfo.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/SystemInfo.java @@ -17,8 +17,10 @@ */ package org.jackhuang.hmcl.util.platform; +import org.jackhuang.hmcl.util.DataSizeUnit; import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard; import org.jackhuang.hmcl.util.platform.hardware.HardwareDetector; +import org.jackhuang.hmcl.util.platform.hardware.PhysicalMemoryStatus; import org.jackhuang.hmcl.util.platform.linux.LinuxHardwareDetector; import org.jackhuang.hmcl.util.platform.macos.MacOSHardwareDetector; import org.jackhuang.hmcl.util.platform.windows.WindowsHardwareDetector; @@ -44,13 +46,15 @@ public final class SystemInfo { DETECTOR = new HardwareDetector(); } + public static final long TOTAL_MEMORY = DETECTOR.getTotalMemorySize(); public static final @Nullable List GRAPHICS_CARDS = DETECTOR.detectGraphicsCards(); } public static void initialize() { StringBuilder builder = new StringBuilder("System Info:"); - List graphicsCards = getGraphicsCards(); + // Graphics Card + List graphicsCards = getGraphicsCards(); if (graphicsCards != null) { if (graphicsCards.isEmpty()) builder.append("\n - GPU: Not Found"); @@ -64,18 +68,46 @@ public final class SystemInfo { } } - OperatingSystem.PhysicalMemoryStatus memoryStatus = OperatingSystem.getPhysicalMemoryStatus(); - if (memoryStatus.getTotal() > 0 && memoryStatus.getAvailable() > 0) { - builder.append("\n - Memory: ") - .append(String.format("%.2f GiB / %.2f GiB (%d%%)", - memoryStatus.getUsedGB(), memoryStatus.getTotalGB(), - (int) (((double) memoryStatus.getUsed() / memoryStatus.getTotal()) * 100) - )); - } + // Memory + long totalMemorySize = getTotalMemorySize(); + long usedMemorySize = getUsedMemorySize(); + + builder.append("\n - Memory: ") + .append(DataSizeUnit.format(usedMemorySize)) + .append(" / ") + .append(DataSizeUnit.format(totalMemorySize)); + + if (totalMemorySize > 0 && usedMemorySize > 0) + builder.append(" (").append((int) (((double) usedMemorySize / totalMemorySize) * 100)).append("%)"); LOG.info(builder.toString()); } + public static PhysicalMemoryStatus getPhysicalMemoryStatus() { + long totalMemorySize = getTotalMemorySize(); + long freeMemorySize = getFreeMemorySize(); + + return totalMemorySize > 0 && freeMemorySize >= 0 + ? new PhysicalMemoryStatus(totalMemorySize, freeMemorySize) + : PhysicalMemoryStatus.INVALID; + } + + public static long getTotalMemorySize() { + return Holder.TOTAL_MEMORY; + } + + public static long getFreeMemorySize() { + return Holder.DETECTOR.getFreeMemorySize(); + } + + public static long getUsedMemorySize() { + long totalMemorySize = getTotalMemorySize(); + if (totalMemorySize <= 0) + return 0; + + return Long.max(0, totalMemorySize - getFreeMemorySize()); + } + public static @Nullable List getGraphicsCards() { return Holder.GRAPHICS_CARDS; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/hardware/HardwareDetector.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/hardware/HardwareDetector.java index 52dc1ddeb..542982fb9 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/hardware/HardwareDetector.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/hardware/HardwareDetector.java @@ -19,13 +19,40 @@ package org.jackhuang.hmcl.util.platform.hardware; import org.jetbrains.annotations.Nullable; +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; import java.util.List; /** * @author Glavo */ +@SuppressWarnings("ALL") public class HardwareDetector { public @Nullable List detectGraphicsCards() { return null; } + + public long getTotalMemorySize() { + try { + OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean(); + if (bean instanceof com.sun.management.OperatingSystemMXBean) { + return ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize(); + } + } catch (NoClassDefFoundError ignored) { + } + + return 0L; + } + + public long getFreeMemorySize() { + try { + OperatingSystemMXBean bean = ManagementFactory.getOperatingSystemMXBean(); + if (bean instanceof com.sun.management.OperatingSystemMXBean) { + return ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getFreePhysicalMemorySize(); + } + } catch (NoClassDefFoundError ignored) { + } + + return 0L; + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/hardware/PhysicalMemoryStatus.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/hardware/PhysicalMemoryStatus.java new file mode 100644 index 000000000..2fc6660a8 --- /dev/null +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/hardware/PhysicalMemoryStatus.java @@ -0,0 +1,46 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2025 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.platform.hardware; + +public final class PhysicalMemoryStatus { + private final long total; + private final long available; + + public PhysicalMemoryStatus(long total, long available) { + this.total = total; + this.available = available; + } + + public long getTotal() { + return total; + } + + public long getUsed() { + return hasAvailable() ? total - available : 0; + } + + public long getAvailable() { + return available; + } + + public boolean hasAvailable() { + return available >= 0; + } + + public static final PhysicalMemoryStatus INVALID = new PhysicalMemoryStatus(0, -1); +} diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/linux/LinuxHardwareDetector.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/linux/LinuxHardwareDetector.java index a1793b264..831dea62f 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/linux/LinuxHardwareDetector.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/linux/LinuxHardwareDetector.java @@ -21,7 +21,16 @@ import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard; import org.jackhuang.hmcl.util.platform.hardware.HardwareDetector; +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static org.jackhuang.hmcl.util.logging.Logger.LOG; /** * @author Glavo @@ -34,4 +43,62 @@ public final class LinuxHardwareDetector extends HardwareDetector { return null; return LinuxGPUDetector.detectAll(); } + + private static final Path MEMINFO = Paths.get("/proc/meminfo"); + private static final Pattern MEMINFO_PATTERN = Pattern.compile("^.+:\\s*(?\\d+)\\s*kB?$"); + + private static long parseMemoryInfoLine(final String line) throws IOException { + Matcher matcher = MEMINFO_PATTERN.matcher(line); + if (!matcher.matches()) + throw new IOException("Unable to parse line in /proc/meminfo: " + line); + + return Long.parseLong(matcher.group("value")) * 1024; + } + + @Override + public long getTotalMemorySize() { + try (BufferedReader reader = Files.newBufferedReader(MEMINFO)) { + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("MemTotal:")) { + long total = parseMemoryInfoLine(line); + if (total <= 0) + throw new IOException("Invalid total memory size: " + line + " kB"); + + return total; + } + } + } catch (Throwable e) { + LOG.warning("Failed to parse /proc/meminfo", e); + } + + return super.getTotalMemorySize(); + } + + @Override + public long getFreeMemorySize() { + try (BufferedReader reader = Files.newBufferedReader(MEMINFO)) { + long free = -1L; + + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith("MemAvailable:")) { + long available = parseMemoryInfoLine(line); + if (available < 0) + throw new IOException("Invalid available memory size: " + line + " kB"); + return available; + } + + if (line.startsWith("MemFree:")) + free = parseMemoryInfoLine(line); + } + + if (free >= 0) + return free; + } catch (Throwable e) { + LOG.warning("Failed to parse /proc/meminfo", e); + } + + return super.getFreeMemorySize(); + } } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/Kernel32.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/Kernel32.java index 28eb6120e..854d58305 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/Kernel32.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/Kernel32.java @@ -48,4 +48,9 @@ public interface Kernel32 extends StdCallLibrary { * @see GetUserGeoID function */ int GetUserGeoID(int geoClass); + + /** + * @see GlobalMemoryStatusEx function + */ + boolean GlobalMemoryStatusEx(WinTypes.MEMORYSTATUSEX lpBuffer); } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WinTypes.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WinTypes.java index 53177a797..cc674e744 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WinTypes.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WinTypes.java @@ -60,4 +60,33 @@ public interface WinTypes { ); } } + + /** + * @see MEMORYSTATUSEX structure + */ + final class MEMORYSTATUSEX extends Structure { + public int dwLength; + public int dwMemoryLoad; + public long ullTotalPhys; + public long ullAvailPhys; + public long ullTotalPageFile; + public long ullAvailPageFile; + public long ullTotalVirtual; + public long ullAvailVirtual; + public long ullAvailExtendedVirtual; + + public MEMORYSTATUSEX() { + dwLength = size(); + } + + @Override + protected List getFieldOrder() { + return Arrays.asList( + "dwLength", "dwMemoryLoad", + "ullTotalPhys", "ullAvailPhys", "ullTotalPageFile", "ullAvailPageFile", + "ullTotalVirtual", "ullAvailVirtual", "ullAvailExtendedVirtual"); + } + } + + ; } diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WindowsHardwareDetector.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WindowsHardwareDetector.java index a8e91470a..30d1bdeba 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WindowsHardwareDetector.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/windows/WindowsHardwareDetector.java @@ -21,6 +21,7 @@ import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.IOUtils; +import org.jackhuang.hmcl.util.platform.NativeUtils; import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.hardware.GraphicsCard; import org.jackhuang.hmcl.util.platform.hardware.HardwareDetector; @@ -133,4 +134,36 @@ public final class WindowsHardwareDetector extends HardwareDetector { return Collections.emptyList(); } } + + @Override + public long getTotalMemorySize() { + if (NativeUtils.USE_JNA) { + Kernel32 kernel32 = Kernel32.INSTANCE; + if (kernel32 != null) { + WinTypes.MEMORYSTATUSEX status = new WinTypes.MEMORYSTATUSEX(); + if (kernel32.GlobalMemoryStatusEx(status)) + return status.ullTotalPhys; + else + LOG.warning("Failed to get memory status: " + kernel32.GetLastError()); + } + } + + return super.getTotalMemorySize(); + } + + @Override + public long getFreeMemorySize() { + if (NativeUtils.USE_JNA) { + Kernel32 kernel32 = Kernel32.INSTANCE; + if (kernel32 != null) { + WinTypes.MEMORYSTATUSEX status = new WinTypes.MEMORYSTATUSEX(); + if (kernel32.GlobalMemoryStatusEx(status)) + return status.ullAvailPhys; + else + LOG.warning("Failed to get memory status: " + kernel32.GetLastError()); + } + } + + return super.getFreeMemorySize(); + } } diff --git a/HMCLCore/src/test/java/org/jackhuang/hmcl/util/DataSizeUnitTest.java b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/DataSizeUnitTest.java new file mode 100644 index 000000000..cecd22f6b --- /dev/null +++ b/HMCLCore/src/test/java/org/jackhuang/hmcl/util/DataSizeUnitTest.java @@ -0,0 +1,65 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2025 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.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public final class DataSizeUnitTest { + + @Test + public void testToString() { + assertEquals("0 bytes", DataSizeUnit.format(0)); + assertEquals("1 byte", DataSizeUnit.format(1)); + assertEquals("2 bytes", DataSizeUnit.format(2)); + assertEquals("100 bytes", DataSizeUnit.format(100)); + assertEquals("1023 bytes", DataSizeUnit.format(1023)); + assertEquals("1 KiB", DataSizeUnit.format(1024)); + assertEquals("1 KiB", DataSizeUnit.format(1025)); + assertEquals("1.07 KiB", DataSizeUnit.format(1100)); + assertEquals("4 KiB", DataSizeUnit.format(4096)); + assertEquals("1 MiB", DataSizeUnit.format(1024 * 1024)); + assertEquals("1.5 MiB", DataSizeUnit.format((long) (1.5 * 1024 * 1024))); + assertEquals("1 GiB", DataSizeUnit.format(1024 * 1024 * 1024)); + assertEquals("1.5 GiB", DataSizeUnit.format((long) (1.5 * 1024 * 1024 * 1024))); + assertEquals("1 TiB", DataSizeUnit.format(1024L * 1024 * 1024 * 1024)); + assertEquals("1.5 TiB", DataSizeUnit.format((long) (1.5 * 1024 * 1024 * 1024 * 1024))); + } + + @Test + public void testConvertFromBytes() { + assertEquals(1, DataSizeUnit.KILOBYTES.convertFromBytes(1024L)); + assertEquals(1.5, DataSizeUnit.KILOBYTES.convertFromBytes((long) (1024. * 1.5))); + + assertEquals(1, DataSizeUnit.MEGABYTES.convertFromBytes(1024L * 1024)); + assertEquals(1.5, DataSizeUnit.MEGABYTES.convertFromBytes((long) (1024 * 1024 * 1.5))); + } + + @Test + public void testConvertToBytes() { + assertEquals(10., DataSizeUnit.BYTES.convertToBytes(10)); + assertEquals(10. * 1024, DataSizeUnit.KILOBYTES.convertToBytes(10)); + assertEquals(10. * 1024 * 1024, DataSizeUnit.MEGABYTES.convertToBytes(10)); + assertEquals(10. * 1024 * 1024 * 1024, DataSizeUnit.GIGABYTES.convertToBytes(10)); + assertEquals(10. * 1024 * 1024 * 1024 * 1024, DataSizeUnit.TERABYTES.convertToBytes(10)); + } + + private DataSizeUnitTest() { + } +}