Skip to content

Commit 143dda4

Browse files
committed
Strip memory arguments from Decompiler task, trusting java to allocate enough.
1 parent 4288f29 commit 143dda4

2 files changed

Lines changed: 72 additions & 13 deletions

File tree

src/main/java/net/minecraftforge/mcmaven/impl/Mavenizer.java

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,18 +74,61 @@ public static boolean checkCache(File output, HashStore cache) {
7474
public static void setDecompileMemory(String value) {
7575
decompileMemory = value;
7676
}
77-
public static List<String> fillDecompileJvmArgs(List<String> args) {
78-
return fillJvmArgs(decompileMemory, args);
77+
78+
// Default java argumetns are built build by the Image, and env variables
79+
// https://github.com/openjdk/jdk/blob/08c8520b39083ec6354dc5df2f18c1f4c3588053/src/hotspot/share/runtime/arguments.cpp#L3628
80+
private static final String[] DEFAULT_ARG_ENV = { "JAVA_OPTIONS", "_JAVA_OPTIONS", "JAVA_TOOL_OPIONS"};
81+
private static final String[] MEMORY_FLAGS = {"-Xmx", "-XX:MaxHeapSize", "-Xms"};
82+
private static void warnAboutMemory() {
83+
var found = false;
84+
for (var env : DEFAULT_ARG_ENV) {
85+
var value = System.getenv(env);
86+
if (value == null)
87+
continue;
88+
for (var flag : MEMORY_FLAGS) {
89+
if (value.contains(flag)) {
90+
LOGGER.warn("Detected Heap Size Argument(" + flag + ") in " + env + " environment variable.");
91+
found = true;
92+
}
93+
}
94+
}
95+
if (found)
96+
LOGGER.warn("Please remove it if you run into memory related issues");
97+
}
98+
99+
public static List<String> fillDecompileJvmArgs(List<String> args, boolean firstRun) {
100+
if (!firstRun)
101+
return args; // Use the unmodifed args from MCPConfig
102+
103+
var ret = stripMemoryJvmArgs(args);
104+
// If we have an explicit memory size use it
105+
if (decompileMemory != null) {
106+
ret.add("-Xmx" + decompileMemory);
107+
} else {
108+
// Don't use any memory arguments and hope java picks the correct values
109+
// By default it is 1/4th physical memory on modern JVMs
110+
// https://docs.oracle.com/en/java/javase/21/gctuning/ergonomics.html
111+
// There are old JVMs that limit it to 1GB but there is no good way to detect if we're using one so just hope.
112+
// https://docs.oracle.com/javase/8/docs/technotes/guides/vm/gctuning/ergonomics.html
113+
// Best we can do is warn about memory argumetns if we see them.
114+
warnAboutMemory();
115+
}
116+
return ret;
79117
}
80-
private static List<String> fillJvmArgs(@Nullable String mx, List<String> args) {
81-
if (mx == null)
82-
return args;
83-
var ret = new ArrayList<String>();
84-
ret.add("-Xmx" + mx);
118+
119+
private static List<String> stripMemoryJvmArgs(List<String> args) {
120+
var ret = new ArrayList<String>(args.size());
121+
85122
for (var arg : args) {
86-
if (arg.startsWith("-Xmx"))
87-
continue;
88-
ret.add(arg);
123+
var skip = false;
124+
for (var flag : MEMORY_FLAGS) {
125+
if (arg.startsWith(flag)) {
126+
skip = true;
127+
break;
128+
}
129+
}
130+
if (!skip)
131+
ret.add(arg);
89132
}
90133
return ret;
91134
}

src/main/java/net/minecraftforge/mcmaven/impl/repo/mcpconfig/MCPTaskFactory.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Set;
2121
import java.util.TreeSet;
2222
import java.util.function.BiPredicate;
23+
import java.util.function.ToIntFunction;
2324
import java.util.jar.JarEntry;
2425
import java.util.jar.JarFile;
2526
import java.util.jar.JarInputStream;
@@ -827,10 +828,23 @@ private File execute(String name, List<TaskOrArg> jvmArgs, List<TaskOrArg> runAr
827828
throw new IllegalStateException("Failed to find JDK for version " + java_version, e);
828829
}
829830

830-
if (isDecompile)
831-
jvm = Mavenizer.fillDecompileJvmArgs(jvm);
831+
ToIntFunction<String> logHandler = null;
832+
if (isDecompile) {
833+
jvm = Mavenizer.fillDecompileJvmArgs(jvm, true);
834+
logHandler = MCPTaskFactory::parseDecompileLog;
835+
}
832836

833-
var ret = ProcessUtils.runJar(jdk, log.getParentFile(), log, tool, jvm, run, isDecompile ? MCPTaskFactory::parseDecompileLog : null);
837+
var ret = ProcessUtils.runJar(jdk, log.getParentFile(), log, tool, jvm, run, logHandler);
838+
if (ret.exitCode == OUT_OF_MEMORY && isDecompile) {
839+
var newJvm = Mavenizer.fillDecompileJvmArgs(resolveArgs(cache, tasks, jvmArgs), false);
840+
if (!newJvm.equals(jvm)) {
841+
LOGGER.error("First decompile failed with OutOfMemory using JVM Args: " + jvm);
842+
LOGGER.error("Attempting again with: " + newJvm);
843+
ret = ProcessUtils.runJar(jdk, log.getParentFile(), log, tool, newJvm, run, logHandler);
844+
if (ret.exitCode == OUT_OF_MEMORY)
845+
LOGGER.error("Ran out of memory again, you can specify more manually using the --decompile-memory Mavenizer argument");
846+
}
847+
}
834848
if (ret.exitCode != 0)
835849
throw new IllegalStateException("Failed to run MCP Step (exit code " + ret.exitCode + "), See log: " + log.getAbsolutePath());
836850

@@ -892,6 +906,8 @@ private List<String> resolveArgs(HashStore cache, Map<Task, String> tasks, List<
892906
private static int parseDecompileLog(String line) {
893907
if (line.startsWith("java.lang.OutOfMemoryError:"))
894908
return OUT_OF_MEMORY;
909+
if (line.startsWith("Exception in thread") && line.contains("java.lang.OutOfMemoryError"))
910+
return OUT_OF_MEMORY;
895911
if (line.contains("ERROR:")) {
896912
// String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + cl.qualifiedName + " couldn't be written.";
897913
// String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " in class " + classWrapper.getClassStruct().qualifiedName + " couldn't be written.";

0 commit comments

Comments
 (0)