A downloadable jvm

Introduction

This is a from-scratch JVM implementation for Sega Dreamcast, from zero to 3D spinning translucent textured cubes in 14 days.

This is not a port of the JVM from the OpenJDK project, but instead a completely separate and independent implementation that follows the same specification.

My time on this project was split roughly 3 ways:

  • 30% of my time was spent writing the actual JVM itself
  • 30% on writing new Java libraries for manipulating the Dreamcast hardware
  • 30% on writing a ”load Java classes the Dreamcast GDROM drive” loader.
  • 10% on designing Java APIs, (and reviewing existing APIs, e.g: java.nio/sun.misc), particularly related to giving Java code direct and arbitrary access to Dreamcast memory/registers

Project links

For more information, see the project website:

 https://dreamcast.idk.st/jvm/

Source code is mirrored to Github:

https://github.com/buhman/jvm

How much of this cube demo is written in Java?

To the greatest extent that Java (a language that does not have memory address dereferences as a built-in language construct) is able, all manipulations of Dreamcast hardware and memory state are manipulated directly from Java code. Memory access occurs either directly via the Memory.getU4 and Memory.putU4 static methods, or indirectly via the Dreamcast DMA controllers.

There are no “foreign calls” to C libraries whatsoever.

The cube demo is 100% native Java.

Current status

The current Dreamcast JVM implementation is fairly complete, and will correctly interpret a wide range of Java code correctly.

However, the following JVM features are not supported:

  • exceptions (try/catch/finally in Java)
  • separately from the above, finally clauses from Java versions ≤1.4 (2002 or earlier)
  • invokedynamic (Java lambdas, Java string concatenation, etc...)
  • synchronized methods (Java threads are also not implemented)
  • runtime type checks (instanceof/checkedcast) on zero-length/null arrays of references
  • garbage collection and memory deallocation (technically not required of a JVM, but fair to expect of a JVM that this exists)

The above list is probably exhaustive. An attempt to do any of these will trigger a failed assertion, and JVM execution will halt.

Other than above list, generally speaking Java class files emitted by any Java version from 6 through 23 inclusive should be compatible with the Dreamcast JVM.

How does the demo work?

I believe it could be interesting if it were possible to author code for the Dreamcast without GCC/binutils. In service to this idea, I designed this multi-stage “boot” process. The boot process allows Java class files to be automatically loaded from iso9660 on a CD, rather than embedded in another binary file via a specialized toolchain.

This means that anyone with a generic javac, mkisofs, and copies of jvm.bin and gdrom_jvm_boot.bin can write code for the Dreamcast.

Dreamcast JVM boot process

Could the Dreamcast JVM also work on Sega Saturn?

Yes.

Java float and double primitives are perhaps the only obstacle.

Though the JVM specification does clearly specify that float and double must be in IEEE-754 format, I think it would be interesting to instead implement float as 16.16 fixed-point, and double as 32.32 fixed-point on Saturn in deliberate violation of the specification.

Implementing fixed-point operations as primitive types rather than as a “FixedPoint” class in Java would also yield significantly better performance—arithmetic opcode execution is practically ”free” compared to the expense of resolving and calling instance methods, not even considering the additional pointer indirections.

What about JVM languages other than Java?

Kotlin “hello world” works in the current Dreamcast JVM implementation:

fun main() {
    println("Hello world!")
} 

I did not test beyond this.

The most probable issue with attempts to run Kotlin/Clojure/Jython, etc... (and in particular their interpreters) on the Dreamcast JVM is most of the Java SE class library is missing. This is not a hard issue to solve; perhaps just slightly tedious at worst.

Why can’t you just use the Java SE libraries from OpenJDK with the Dreamcast JVM?

The OpenJDK class libraries depend on the OpenJDK JVM’s internals (for which there is no formal specification).

What about performance? Is the Dreamcast JVM fast?

Absolutely not.

On the current JVM implementation, expect performance somewhere on the order of 100x slower than semantically-equivalent C code as compiled by GCC.

The fact that my cube demo spins at all at relatively nice-looking framerates is a testament to the brute speed of the SH7091 SH4 CPU in the Dreamcast.

Could Dreamcast JVM performance improve?

The Dreamcast JVM is a fairly naive bytecode interpreter, so there are myriad ways to improve performance. For long sequences of arithmetic operations (e.g: a vertex transformation function), it is fairly obvious that the solution should be to JIT-compile the bytecodes to SH instructions. I think this should be fairly easy to do.

While there have been several ”JIT-compile SH to x86” projects (as in Dreamcast emulators), I am not aware of any ”JIT-compile [thing] to SH” projects. This adds to the list of reasons why I think this would be interesting to pursue.

Indepent of bytecode execution: method lookups, and particularly instance method lookups, are slower than they could be. Perhaps in parallel with the JIT effort, with a more thorough “linking” process, method lookups could likely become about as fast as calling a function pointer in C.

Does this mean Java ME games for early 2000’s mobile phones could be run on Dreamcast?

I like this idea. Unlike Java SE, which is fairly huge, implementing the Java ME class libraries feels closer to what could be a one-person initiative.

It could also be fun to implement the “Mobile 3D Graphics” Java ME profiles for Dreamcast.

What about .NET/CLR for Dreamcast/Saturn?

The Dreamcast JVM project would not have been possible without the excellent and freely-available specification:

https://docs.oracle.com/javase/specs/jvms/se23/html/index.html

I am aware that a CLR/CLI/CIL specification exists as well:

https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf

The ECMA-335 specification looks fairly complete/implementable, and I estimate such a project would be roughly on the same level of effort as this JVM project.

I don’t know. Maybe?

Other possible future directions

I am interested in hearing anyone’s opinions on any topic even vaguely related to any of the above.

Published 2 days ago
StatusIn development
CategoryTool
Authorpurist
Tags3D, Dreamcast, java, No AI

Download

Download
jvm-cube-usb-uart.bin 1.1 MB
Download
jvm-cube-flycast.cdi 3.1 MB
Download
jvm-cube-dreamcast.cdi 4.3 MB