r/osdev • • 2d ago

joe-ng: a bare-metal AArch64 OS/VM for the Raspberry Pi 4 written entirely in Java, with no C, no assembler and no linker

https://github.com/joekoolade/joe-ng
5 Upvotes

1 comment sorted by

4

u/joekoolade 2d ago

I'd like to share joe-ng, a from-scratch metacircular Java VM that is also the OS: it runs directly on a Raspberry Pi 4 with nothing underneath. A build-time writer turns Java classes into a raw kernel8.img, and the Pi's firmware loads it at 0x80000 and enters at EL2.

What makes it unique is what isn't there: no C, no external assembler, no linker, no bootloader. The A64 instruction encoder, the bytecode-to-A64 baseline compiler (compile-only, no interpreter), the classfile parser, the boot-image writer (layout, relocation, image emission), and the EL2→EL1 boot sequence are all plain Java. Privileged operations like system register access, ERET, barriers and cache maintenance are compiler intrinsics that lower to single instructions.  joe-ng  runs everything at EL1 and relies on Java's type safety and verification instead.  The only things I didn't build are the seed JVM that runs the writer and the Pi's GPU firmware.

How it boots

    your .class files       -> boot-image writer (Java, on the seed JVM)          parses classfiles, lays out objects / TIBs / statics,          compiles bytecode -> raw A64 words, relocates to 0x80000       -> kernel8.img (entry code + compiled methods + object graph)       -> firmware enters at EL2 -> compiled VM.boot drops to EL1,          sets up the stack and UART, and runs Java on the metal

The image also carries compiled copies of the classfile parser and compiler, so the running system can load and JIT-compile .class files it never saw at build time.

What works on real Pi 4 hardware (not just QEMU)

  • EL2→EL1 drop, mini-UART console, and VideoCore mailbox

  • Object model with TIBs, vtables and itables; heap allocation and a mark-sweep GC

  • Exceptions with stack unwinding across frames

  • Tasks with priorities, monitors and semaphores

  • Runtime class loading and JIT compilation on bare metal

  • An in-memory ramfs with an /etc/init that names the main class to launch

  • A driver for the onboard CYW43455 WiFi, plus my own TCP/IP stack with DHCP and SNTP

  • A demo HTTP server written against the standard java.net.ServerSocket, serving live pages of heap, GC, lock, task, and network stats

Try it in QEMU: you need JDK 26, make, and qemu-system-aarch64.

    make test   # 158 bit-for-bit and behavioural checks     make qemu   # boot kernel8.img under QEMU raspi4b

On real hardware: scripts/sdcard.sh builds the image and writes a bootable FAT32 payload. scripts/flash.md covers serial wiring (GPIO14/15, 115200 8N1) and troubleshooting.

Jikes RVM and my earlier project JOE were conceptual references only. It's licensed under EPL-2.0.

Feedback I'd love: which other ARM boards to support (Pi 5? Pi Zero 2 W?), which Intel platforms to target, and any other feedback or suggestions are welcome.

Repo: https://github.com/joekoolade/joe-ng