Baconium/iOS-JVM-s

patches for OpenJDK JVM's to build JVM's for iOS (even supports iOS 27!!! wow!!!)

★ 0Forks 0ShellGitHub ↗Compare

README

iOSJVM

OpenJDK 8, 17, 21, and 25 JVM's for iOS (and other darwin based OS's prolly idk I havent tested). requires JIT in order to run

This repo just has a few patches for the upstream OpenJDK plus build scripts, not the full source OpenJDK source code

Version Upstream Patches
8 corretto/corretto-8 tag 8.472.08.1 jre_8/ios/
17 openjdk/jdk17u @ 7d4b790cd43a jre_17/ios/
21 openjdk/jdk21u tag jdk-21.0.8+7 jre_21/ios/
25 openjdk/jdk25u tag jdk-25.0.1+8 jre_25/ios/

all of the versions effectively share the same patches:

  1. 1_jdk*_ios.diff – build system and libjava/libnet/libjsound changes so OpenJDK cross-compiles for aarch64-apple-ios
  2. 2_mirror_mapping.diff – HotSpot "mirror mapped" code cache. Basically, TXM on iOS 26+ refuses to execute pages that were ever writable. this shit just "mirror maps" pages to RX pages that JIT cant write to (very technical I know). enable this by passing -XX:+MirrorMappedCodeCache
  3. 3_no_cocoa_relay.diff – libjli: macOS handles the JVM differently in how it's spawned, this disables some macOS shit on iOS (without this, JESSI tried to spawn 2 JVM's. this prolly could've been fixed by changing how JESSI works rather than patching this, but fuck you I'm lazy and this works just fine)

Usage

if you also happen to be making an iOS app that requires a JVM, load libjli.dylib, call JLI_Launch, and pass these arguments (MirrorMappedCodeCache can be omitted on iOS 18.x and earlier):

-XX:+UnlockExperimentalVMOptions -XX:+DisablePrimordialThreadGuardPages -XX:+MirrorMappedCodeCache

On "TXM devices", you must also do this shit:

  • enable JIT via a debugger (this is pretty much the only way to enable JIT on non jailbroken non trollstore iOS anyways, feel free to skid JESSI's JITHelper if you're confused)
  • tell the JVM's brk #0x69 code-cache request to fuck off so the JVM maps it itself, then prepare that RX mapping via the debugger before the JVM fucks it up
  • keep mprotect/madvise out of the RX code cache (older libjvm builds break execution of the RX pages, not good)
  • keep the code cache at like 32M, unless you want your app to run at 1 frame per minute

JESSI's JessiJavaRunner.m has all of this shit in it, so technically you could use it as a reference, but I would strongly advise against EVER opening that file or reading its contents. you will regret it.

Other Notes

if you're unsure what devices are "TXM devices", please refer to this handy dandy table:

|---|---|---| |iOS 18-|iOS 26|iOS 27+| |None|A15+ and M2+|A13+ and M1+|

don't know what that means? cool! you probably shouldn't be developing an app for iOS that requires JIT or a JVM! (or you could just google which devices have which chipsets idk)

(side note: technically A15+/M2+ have TXM on iOS 17 and 18, but it doesn't interfere with JIT. you do not need to do the extra TXM shit or attach a JIT script on iOS 18 and earlier, no matter what the device is. there is also only one device that is able to use i(Pad)OS 27 that does not support TXM, that being the 4th gen iPad Pro)

MirrorMappedCodeCache on java 8 may be a bit unstable by the way, if you run into issues with it you should probably just use a newer JVM instead. theres quite honestly no real reason to use java 8 anyways

please also note that this shits mostly vibecoded, I did however go through and verify everythings at least somewhat not complete dogshit though. I usually remove AI generated slop comments from my projects, but I decided against doing so this time half because I'm lazy and half because this shits such a pain in the ass that its prolly worth leaving at least some frame of reference in it the code. anyways tho, good luck with whatever app you're making!

Issues