PanamaKVM is an experimental miniVM containing the bare minimum components needed to boot an x86 Linux kernel and run an interactive terminal. Its key feature is that it is built on top of Java 25 without using JNI. Instead, it utilizes the Foreign Function & Memory API (FFM).
I generally stick to Java LTS versions - having worked with Java 21 for a long time - so I recently decided to check if any new LTS releases had come out. It turns out I was a year late to the party regarding Java 25. While looking through the changelog, I noticed the new FFM for native code and decided to give it a try.
As it turned out, I was a couple of years late to the FFM feature :D, since it had already been introduced as a full-fledged part of the language in Java 22.
One interesting thing I discovered during implementation was a quirk in the ioctl ABI: there seemed to be a discrepancy between the KVM API documentation and the actual implementation. The very first call I attempted was KVM_GET_API_VERSION, but it unexpectedly returned EINVAL. After tracing the execution with strace, I managed to pinpoint the root cause (which was nearly impossible to debug at the Java level): the call was reaching the kernel without a third argument (whereas the documentation specified two). As it turns out, when the KVM documentation says an ioctl takes no arguments, it actually does require one... Due to KVM's implementation details, it implicitly expects a third parameter - it just has to be zero. This is likely to prevent reading garbage data from memory. Perhaps some readers have insights into the underlying reason for this difference - or maybe it was just human error and "things just turned out that way."
In any case, by following the instructions in the repository's README, you can boot a functional Linux kernel and interact with it via the terminal. I’ve only tested the launch using Alpine 3.24.2 x86-64 on WSL2, so that might be a limitation. However, if you run it on a different setup or on bare-metal Linux, that would be great - please let me know. And if something breaks in the process - even better - let me know about that too.
As for what I haven't finished yet in the current virtual machine implementation: networking and persistent storage are missing, and there is no virtio integration. Multi-vCPU startup mode isn't supported either; essentially, the creation of a single vCPU is currently hardcoded.
I’d also love to hear your thoughts on the project. I would particularly value any feedback regarding the use of FFM and the KVM API itself.
I’ll be happy to answer any questions you have.