Minecraft Java Edition is a desktop-only game. It expects a real JVM, it talks to the GPU using desktop OpenGL, and it was never built with a touchscreen in mind. And yet there's a small ecosystem of Android apps that run it — not a Bedrock reskin, the actual Java Edition, mods and all. How?
Problem #1: There's no JVM on your phone
Android apps run on ART (the Android Runtime), which executes Dex bytecode compiled from Kotlin/Java — but it is not a general-purpose desktop JVM. It can't just java -jar an arbitrary jar the way your laptop can.
The launchers that pull this off (Zalith Launcher, PojavLauncher, and forks of both) solve this by bundling an actual ARM-compiled OpenJDK-compatible JVM inside the app, and running the real Minecraft client jar on top of that, sandboxed inside the Android app's process. It's less "porting Minecraft to Android" and more "smuggling a JVM onto your phone and handing Minecraft the keys."
Problem #2: Minecraft speaks desktop OpenGL, your phone doesn't
Even with a working JVM, Minecraft's renderer is hardcoded against desktop OpenGL. Mobile GPUs generally expose OpenGL ES and, on newer devices, Vulkan — not the desktop GL profile Minecraft expects. So the JVM might run fine and still get nowhere the moment the game tries to draw a frame.
This is where Zink comes in: a Mesa driver that translates OpenGL calls into Vulkan commands at runtime. Instead of needing a native desktop-OpenGL driver on the GPU (which mobile chipsets don't ship), the app translates Minecraft's OpenGL calls into Vulkan ones, which the phone's GPU can actually execute.
Zalith Launcher 2, an open-source launcher on GitHub, is a good real-world example of this pipeline in production. Its release notes are a decent public record of how fiddly this translation layer is in practice:
- It shipped with a renderer called VulkanZink for a while.
- In version 2.4.10, the renderer was swapped to Kopper Zink, specifically to improve compatibility and support a newer Minecraft version.
- Its 2.3.3 changelog carries an explicit compatibility warning: since Minecraft 26.2+, Mojang itself started using a native Vulkan renderer — meaning if the device's GPU doesn't support Vulkan 1.2, the latest Minecraft versions won't launch at all, independent of the Zink layer.
That last point is a nice illustration of how these translation stacks are never "solved once" — the target (Mojang's own renderer) keeps moving too.
The JVM doesn't stop mattering just because it's on a phone
Once you've got a JVM and a working render path, you're still running actual Java Edition — which means the usual JVM tuning still applies, just squeezed into a phone's memory and thermal budget:
-
-Xmx/-Xmsheap sizing still matters, and getting it wrong (too low or too high) causes real stutter from GC pressure, not just "not enough RAM." - Choosing between Vulkan, OpenGL, and Zink backends isn't cosmetic — it's the difference between the game launching at all on some chipsets.
- 32-bit vs. 64-bit builds change how much address space the JVM even gets to work with.
I wrote up a deeper practical breakdown of exactly how to tune this stuff — heap sizing per RAM tier, when to pick which renderer, why 64-bit matters — here, if you want to go further than the "why does this work at all" level.
It's a fun little corner of software engineering: an entire desktop runtime and rendering stack, smuggled onto a phone, held together by a translation layer most people never think about.