【免费下载链接】MojoLauncher
A Minecraft: Java Edition launcher, based on PojavLauncher
MojoLauncher 是基于 PojavLauncher 的 Minecraft: Java Edition 安卓启动器,能在手机上运行几乎全部 Minecraft 版本,并支持直接用.jar安装器安装 Forge 等模组加载器。那么,手机凭什么能打开一个典型的"桌面 Java 程序"?本文带你剖析它背后的 AWT 图形界面方案与 caciocavallo 实现原理。
一、问题起点:Forge 安装器为什么必须"看见"窗口
在电脑上双击forge-installer.jar,你会看到一个标准的 Swing 窗口:版本选择、安装类型、一个"安装"按钮。这套图形界面依赖 Java 的 AWT/Swing 体系。
但在 Android 上:
- Android 没有 AWT/Swing,原生 Java 图形栈是 View/Canvas 体系;
- Minecraft 本体走 LWJGL 渲染管线,与 AWT 无关;
- 启动器若直接运行安装器 JAR,会因找不到图形环境而崩溃。
MojoLauncher 的解法不是"模拟点击"黑盒,而是给手机上的 JVM 装上一套可工作的 AWT 实现,让安装器像运行在 Linux/X11 桌面一样正常启动、绘制、响应鼠标键盘。
二、整体架构:三层各司其职
| 层次 | 角色 | 关键代码 |
|---|---|---|
| Android 应用层 | 承载安装器界面、采集触摸/按键 | AWTActivity.java、AWTBackend.java |
| JVM 层 | 提供"虚拟 AWT 桌面":工具包、屏幕帧缓冲、输入入口 | caciocavallo(CTCToolkit/CTCGraphicsEnvironment/CTCScreen) |
| 原生桥接层 | 渲染像素到屏幕、注入输入事件、桥接剪贴板 | awt_window.c、awt_input.c |
三者通过 JNI 串联:Android 界面产生触摸 → JNI 注入到 JVM 内的 AWT 事件队列 → Swing 组件响应 → 画面写进 caciocavallo 的内存屏幕 → 原生线程把像素刷到手机 Surface。
三、caciocavallo:给 Java 装上一块"虚拟显示屏"
caciocavallo 延续了 Cacio 项目的 CTC 工具包思路,是运行在 Android JVM 里的 AWT 替代实现。启动器在 JavaRunner.java 中为它做了两套"接线":
- Java 8 运行时:通过
-Xbootclasspath/p把 caciocavallo 的 jar 前置到引导类路径,并设置-Dawt.toolkit=net.java.openjdk.cacio.ctc.CTCToolkit、-Djava.awt.graphicsenv=...CTCGraphicsEnvironment; - Java 17+ 运行时:改用
-javaagent注入字节码增强,并追加一组--add-exports/--add-opens模块开放参数,因为新模块化 JDK 不再允许随意触碰 AWT 内部包。
同时还有几个"欺骗环境"的关键参数:-Djava.awt.headless=false(声称有显示环境)、-Dcacio.managed.screensize=1024x768(虚拟屏幕分辨率,见 awt.h)、以及指定 X11 字体管理器 + FreeType 字体缩放器,让 Swing 文本正常渲染。
这些组件 jar 由构建脚本自动拉取到 assets/components/caciocavallo/ 并在首次启动时解包(见 build.gradle、AsyncAssetManager.java)。
四、原生渲染管线:每 4 毫秒把"内存屏幕"刷上真屏幕
caciocavallo 把整个窗口系统画在一块CTCScreen的 RGB 像素数组里。原生侧的 render_loop_thread 则承担"显示器"的角色:
- 通过 JNI 调用
CTCScreen.getCurrentScreenRGB()取像素缓冲区; ANativeWindow_lock锁定 Android Surface,按行memcpy像素;unlockAndPost提交,然后用clock_nanosleep把帧间隔锁在约 4ms——安装器界面的刷新完全够用。
渲染线程在 JNI_OnLoad 阶段等待游戏运行时 VM 连接后启动;Surface 生命周期由 AWTBackend.surfaceCreated 回调管理。画布尺寸固定为 1024×768,AWTView 负责按这个比例自适应屏幕。
五、触摸变鼠标:输入与剪贴板桥接
桌面安装器要鼠标,手机只有手指。AWTActivity 提供了一整套"虚拟外设":
- 虚拟鼠标:触摸画布拖动移动光标,坐标经 sendScaledMousePosition 换算到 1024×768 虚拟坐标系,单击触发左键;另有独立的左/右键按钮与窗口移动按键(安装器窗口经常需要挪动);
- 事件注入:awt_input.c 中的
nativeSendCursorPos/nativeSendKeyEvent/nativeSendMouseEvent统一把 Android 事件翻译成CTCAndroidInput.receiveData(type, i1, i2, i3, i4)调用,Android 键码还会被转译为 AWT 键码; - 剪贴板:awt_clipboard.c 双向桥接系统剪贴板与 JVM,
Ctrl+C/Ctrl+V在界面上以按钮形式提供。
六、无人值守安装:自动点击"安装"按钮
有了可见、可点的窗口,MojoLauncher 更进一步——它内置了一个 Java Agent:实现AWTEventListener监听WINDOW_OPENED事件,识别出 Forge 安装器主窗口后,遍历组件找到 OK/安装按钮并自动点击,后续对话框由DialogFilter逐个处理,组件超时会由ComponentTimeoutTask兜底。于是用户在手机上"打开安装器"这个动作,常常等于"完成安装"。
安装入口由 InstanceInstaller.executeWithActivity 发起:把安装器 jar 路径与命令行参数打包进 Intent,交给AWTActivity启动。
七、安全细节:陌生人发的 jar 怎么办
AWTActivity启动前会读取 jar 的 Manifest 与主类字节码版本号,经 MultiRTUtils 自动挑选最匹配的 JVM;若安装器来源不受信任且开启了沙箱偏好,会追加 pro-grade 安全管理器与策略文件(java_sandbox.policy),限制任意 jar 的危险行为。
八、关键文件速查
| 内容 | 路径 |
|---|---|
| 安装器 Activity 与虚拟输入 | AWTActivity.java |
| AWT 平台后端 | AWTBackend.java |
| caciocavallo JVM 参数组装 | JavaRunner.java |
| 原生渲染循环 | awt_window.c |
| 输入事件注入 | awt_input.c |
| 剪贴板桥接 | awt_clipboard.c |
| 自动点击代理 | Agent.java |
| 组件资产目录 | assets/components/caciocavallo/ |
总结
MojoLauncher 让手机打开 Forge 安装器的"魔法",本质是一条清晰的三层链路:caciocavallo 在 JVM 内提供完整的 AWT/Swing 运行环境与内存屏幕 → 原生线程把像素帧刷到 Android Surface、并把手势翻译成 AWT 事件 → 安装器 Agent 实现无人值守点击。理解这套 AWT 桥接架构,你也能举一反三:任何依赖 Swing 的桌面 Java 工具,都有机会在安卓上"活"起来。
【免费下载链接】MojoLauncher
A Minecraft: Java Edition launcher, based on PojavLauncher
相关推荐
哈希签名凭什么能抵抗量子计算机攻击?从 WOTS+ 原理到 hashsigs-solidity 实践
哈希签名凭什么能抵抗量子计算机攻击?从 WOTS+ 原理到 hashsigs solidity 实践 量子计算机正在逼近, 哈希签名(Hash based Si
DIY-CNC-machine完全指南:从零开始打造你的首台数控雕刻机
DIY CNC machine完全指南:从零开始打造你的首台数控雕刻机 DIY CNC machine是一个开源项目,提供了从零基础构建数控雕刻机的完整指南。本
硬件开发用图像识别驱动游戏AI:GameAISDK自动化测试框架的完整上手路线
用图像识别驱动游戏AI:GameAISDK自动化测试框架的完整上手路线 如果你是游戏测试或AI开发的新手,多半被这样一件事困扰过:想给游戏写自动化测试,却发现市
人工智能强化学习计算机视觉游戏开发测试
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考