You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自制Minecraft启动器无法正常启动进程的原因排查

问题描述

学校电脑会阻止未知应用或.exe文件,但已安装Java,因此我写了个替代官方Minecraft启动器的自定义启动系统。原本可以生成命令粘贴到唯一未被封禁的终端Powershell ISE里启动游戏,但为了方便非技术用户,我想让程序自行启动游戏。

我用了这段Java代码:

try {
    /*ProcessBuilder procbuilder = new ProcessBuilder(processArgs);
     procbuilder.inheritIO();
     procbuilder.start();*/
     Runtime.getRuntime().exec(command).waitFor();
} catch (java.io.IOException | java.lang.InterruptedException e) {
     System.out.println("Exception while starting Minecraft: " + e);
}

其中command是在终端能正常运行的有效Java命令,由程序读取模板替换占位符生成。我用exec()能正常启动其他程序,比如:

Runtime.getRuntime().exec("notepad.exe abc.txt");
// or
Runtime.getRuntime.exec(new String[] {"notepad.exe", "abc.txt"});

但启动Minecraft时,ProcessExplorer显示进程已创建,却没有游戏窗口或运行迹象,参数明明是对的,为什么Java启动和终端启动结果不一样?

以下是我尝试运行的完整命令:

java "-Dox.name=Windows 10" "-Dos.version=10.0" "-Djava.library.path=C:\Users\myuser\Desktop\MC1-12-2\javaLibraries\" "-Dminecraft.launcher.brand=sidecraft" "-Dminecraft.launcher.version=2.3.592" "-Dminecraft.client.jar=C:\Users\myuser\Desktop\MC1-12-2\version\1.12.2.jar" -cp "C:\Users\myuser\Desktop\MC1-12-2\libraries\com\mojang\patchy\1.3.9\patchy-1.3.9.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\oshi-project\oshi-core\1.1\oshi-core-1.1.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\net\java\dev\jna\jna\4.4.0\jna-4.4.0.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\net\java\dev\jna\platform\3.4.0\platform-3.4.0.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\ibm\icu\icu4j-core-mojang\51.2\icu4j-core-mojang-51.2.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\net\sf\jopt-simple\jopt-simple\5.0.3\jopt-simple-5.0.3.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\paulscode\codecjorbis\20101023\codecjorbis-20101023.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\paulscode\codecwav\20101023\codecwav-20101023.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\paulscode\libraryjavasound\20101123\libraryjavasound-20101123.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\paulscode\librarylwjglopenal\20100824\librarylwjglopenal-20100824.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\paulscode\soundsystem\20120107\soundsystem-20120107.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\io\netty\netty-all\4.1.9.Final\netty-all-4.1.9.Final.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\google\guava\guava\21.0\guava-21.0.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\apache\commons\commons-lang3\3.5\commons-lang3-3.5.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\commons-io\commons-io\2.5\commons-io-2.5.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\net\java\jinput\jinput\2.0.5\jinput-2.0.5.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\net\java\jutils\jutils\1.0.0\jutils-1.0.0.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\mojang\realms\1.10.22\realms-1.10.22.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\apache\commons\commons-compress\1.8.1\commons-compress-1.8.1.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\apache\httpcomponents\httpclient\4.3.3\httpclient-4.3.3.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\apache\httpcomponents\httpcore\4.3.2\httpcore-4.3.2.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\it\unimi\dsi\fastutil\7.1.0\fastutil-7.1.0.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\apache\logging\log4j\log4j-api\2.8.1\log4j-api-2.8.1.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\apache\logging\log4j\log4j-core\2.8.1\log4j-core-2.8.1.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\lwjgl\lwjgl\lwjgl\2.9.4-nightly-20150209\lwjgl-2.9.4-nightly-20150209.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\org\lwjgl\lwjgl\lwjgl_util\2.9.4-nightly-20150209\lwjgl_util-2.9.4-nightly-20150209.jar;C:\Users\myuser\Desktop\MC1-12-2\libraries\com\mojang\text2speech\1.10.3\text2speech-1.10.3.jar;C:\Users\myuser\Desktop\MC1-12-2\version\1.12.2.jar" -Xmx2G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M "-Dlog4j.configurationFile=C:\Users\myuser\Desktop\MC1-12-2\version\client-1.12.xml" net.minecraft.client.main.Main --version 1.12.2 --accessToken NO_TOKEN --gamedir C:\Users\myuser\Desktop\MC1-12-2 --assetsDir C:\Users\myuser\Desktop\MC1-12-2\assets --assetIndex 1.12 --uuid 4290304c-2bb5-4f73-b5cc-1e545bd766a1 --userType msa --versionType release
原因及解决方法

核心问题:命令解析差异

终端(如Powershell ISE)会自动处理带引号的参数,但Runtime.exec(String)方法不会正确解析包含空格和引号的复杂命令。它会按空格拆分参数,导致带空格的路径、JVM参数被错误分割,Minecraft进程虽然启动,但参数不正确,无法正常初始化窗口。

解决步骤

  1. 改用ProcessBuilder并传入参数数组
    放弃直接传入完整命令字符串,而是将命令拆分为独立的参数数组,确保每个参数被正确传递。比如把java作为第一个元素,每个JVM参数、类路径、主类、游戏参数都作为单独的数组元素。
    示例代码:

    try {
        // 将完整命令拆分为参数数组,注意去掉原来的引号,每个参数单独成项
        String[] processArgs = {
            "java",
            "-Dox.name=Windows 10",
            "-Dos.version=10.0",
            "-Djava.library.path=C:\\Users\\myuser\\Desktop\\MC1-12-2\\javaLibraries\\",
            "-Dminecraft.launcher.brand=sidecraft",
            "-Dminecraft.launcher.version=2.3.592",
            "-Dminecraft.client.jar=C:\\Users\\myuser\\Desktop\\MC1-12-2\\version\\1.12.2.jar",
            "-cp",
            "C:\\Users\\myuser\\Desktop\\MC1-12-2\\libraries\\com\\mojang\\patchy\\1.3.9\\patchy-1.3.9.jar;C:\\Users\\myuser\\Desktop\\MC1-12-2\\libraries\\oshi-project\\oshi-core\\1.1\\oshi-core-1.1.jar;...", // 替换为完整类路径
            "-Xmx2G",
            "-XX:+UnlockExperimentalVMOptions",
            "-XX:+UseG1GC",
            "-XX:G1NewSizePercent=20",
            "-XX:G1ReservePercent=20",
            "-XX:MaxGCPauseMillis=50",
            "-XX:G1HeapRegionSize=32M",
            "-Dlog4j.configurationFile=C:\\Users\\myuser\\Desktop\\MC1-12-2\\version\\client-1.12.xml",
            "net.minecraft.client.main.Main",
            "--version", "1.12.2",
            "--accessToken", "NO_TOKEN",
            "--gamedir", "C:\\Users\\myuser\\Desktop\\MC1-12-2",
            "--assetsDir", "C:\\Users\\myuser\\Desktop\\MC1-12-2\\assets",
            "--assetIndex", "1.12",
            "--uuid", "4290304c-2bb5-4f73-b5cc-1e545bd766a1",
            "--userType", "msa",
            "--versionType", "release"
        };
        ProcessBuilder procBuilder = new ProcessBuilder(processArgs);
        procBuilder.inheritIO(); // 继承父进程IO,方便查看游戏输出日志排查问题
        procBuilder.start();
    } catch (IOException | InterruptedException e) {
        System.out.println("启动Minecraft时发生异常: " + e);
    }
    
  2. 继承IO输出排查问题
    启用procbuilder.inheritIO()后,Minecraft的标准输出和错误输出会直接打印到你的程序控制台,能看到进程启动时的错误信息(比如类找不到、路径错误等),帮助快速定位问题。

  3. 设置进程工作目录
    终端启动时的工作目录可能和你的Java程序不同,Minecraft可能依赖工作目录加载资源。可以用以下代码设置进程的工作目录为游戏所在文件夹:

    procBuilder.directory(new File("C:\\Users\\myuser\\Desktop\\MC1-12-2"));
    
  4. 避免主线程阻塞
    如果你的程序是GUI应用,调用waitFor()会阻塞主线程导致界面无响应,建议去掉waitFor(),或在单独线程中处理进程等待逻辑。

内容的提问来源于stack exchange,提问作者larryr1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 13:31:02