Writing a Toy JVM in Rust

2023/07/13
This article was written by an AI 🤖. The original article can be found here. If you want to learn more about how this works, check out our repo.

In this article, the author shares their experience of writing a Java Virtual Machine (JVM) in Rust. The project, named "rjvm," is a toy JVM built for learning purposes rather than a serious implementation. The code for the project is available on GitHub.

While the author acknowledges that the toy JVM does not support certain features, they have implemented several non-trivial functionalities. For example, the toy JVM uses the real rt.jar containing classes from the OpenJDK 7, allowing it to execute Java code using actual JDK classes.

The author expresses their satisfaction with what they have learned about Rust and implementing a virtual machine. They highlight the successful implementation of a garbage collector, which, although mediocre, is a personal achievement.

Moving forward, the author plans to provide a high-level overview of how their JVM works in this article. They also mention the possibility of writing more detailed articles about specific aspects of the implementation in the future.

Code organization: The code for the toy JVM is organized into three crates (packages) within a standard Rust project. The author is considering extracting the reader crate into a separate repository and publishing it on crates.io, as it could be useful to others.

Parsing a .class file: To execute Java code, the JVM first loads a .class file containing the bytecode generated by the javac compiler. The author has created a separate crate named "reader" to parse the class file and return a Rust struct that models a class and its contents.

Executing methods: The main API of the toy JVM is Vm::invoke, which is used to execute a method. It takes a CallStack, containing CallFrames for each method being executed. Each function invocation adds a new frame to the call stack. When a method's execution completes, its frame is dropped and removed from the call stack.

The toy JVM supports executing both Java methods and native methods. Native methods are implemented directly by the JVM and not in Java bytecode. They are commonly used for low-level interactions with the operating system or runtime support.

Overall, this article provides insights into the process of building a toy JVM in Rust and highlights the author's learnings and achievements. Developers interested in JVM internals and Rust programming may find this project and its future articles valuable resources.