Android / iOS


Java Grinder

Posted: January 05, 2014
Updated: November 20, 2015


Java Grinder is a tool for taking Java .class files compiled with javas as an input and outputs native assembly code for platforms such as microcontrollers, game consoles, and computers. On the microcontrollers, there is a Java API to take advantage of the I/O ports, UART, SPI, and more. On the game console / computer side, there are Java API's to manipulate the graphics and sound chips. Currently, the following CPUs / platforms are supported:

The entire Java Grinder code-base was implemented in a modular way to make easy to add support for different CPUs. I started support with MSP430 and Joe Davisson helped out by adding code for 6502, Atmel AVR8, and W65C816, along with APIs for Commodore 64, Apple IIgs, and W65C265SXB. I added dsPIC, Z80, x86, 68000 with API's for Sega Genesis and start of an API for the TI84 calculator. My current plans are to get MIPS implemented for PIC32 chips and Joe is working on a full API for the W65C265SXB board. Other future plans are to possibly add other byte-code parsers such as .NET so Java Grinder can also compile C# programs into native code, but we'll see if that ever happens. For a more complete description of how Java Grinder works, read the last section of this page.

The purpose of this project (I think for Joe too) is to simply just to learn something new and to create electronic art projects such as graphics and sound demos. I've seen on some forums people talking about this project ripping on Java, so I should also say I'm not this big Java advocate or anything. I picked Java because the people who designed the language did such a slick job on the .class file format and byte-code language that it was pretty easy to write a program like this. Most of the complexity of Java Grinder comes from generators, outputting assembly for the different platforms, and creating easy to use APIs. This project is just flat out fun. For the people who hate Java, my rule is pick the right tool for the right job. Sometimes Java is the right tool.

All generated assembly can be assembled with naken_asm except the x86 code which is assembled with The Netwide Assembler (nasm).

Java Grinder can do bits of optimization to improve the speed of the generated code. For example, despite Java being a stack based language, for most of the implemented CPUs, Java Grinder keeps values in registers. It can also do 1 or 2 instruction look-aheads to find better instructions for certain CPU's. An example of this is explained below. Also, the API is written so that every method is static and when the assembly language is generated, many API methods are replaced with inline assembly instead of function calls.

There are some restrictions with how this works:

  • Some Java byte-code instructions are currently not implemented.
  • The 8 and 16 bit CPUs are currently implemented as 16 bit for performance.
  • Need to implement switch/case.
  • Need to add "new" instructions for objects and virtual method calling (maybe?).
  • Currently no garbage collection or memory protection. Doing new array[] will pull memory from the heap but never free it.
3 billion devices run Java

git clone


Related Projects

Related pages on Sega Genesis Java, Apple IIgs Java, TI99/4A Java, C64 Java, dsPIC Mandelbrots, Java Grinder, naken_asm


Joe Davisson worked on the 6502 support (and Atmel AVR8 support) and made this Commodore 64 demo for Java Grinder.

Source code included in Java Grinder samples directory.

Here is a video of it running on a real C64: C64 Java

dsPIC Mandelbrots in Java

Here's a dsPIC computing Mandelbrots optimized with the dsPIC's DSP instructions. For a full write-up on how this works and a video see here: dsPIC Mandelbrots.

Here's another example showing and MSP430 and a Java Grinder program controlling an LCD display. Source code is again included with package.


In the git repository in the testing directory there is a program called To test it out to see how it works (you'll need to download naken_asm first), do the following:

git clone
cd java_grinder
make java
make tests
./java_grinder testing/LedBlink.class out.asm msp430g2231
naken_asm -l -I ${PATH_TO_NAKEN_MSP430_INCLUDES} out.asm mspdebug rf2500
prog out.hex

The code in looks like this:

  static public void main(String args[])
    int n;


      for (n = 0; n < 16384; n++);
      for (n = 0; n < 16384; n++);

Running javap -c testing/LedBlink.class, the Java assembly looks like this:

  public static void main(java.lang.String[]);
       0: iconst_3      
       // Method net/mikekohn/java_grinder/IOPort0.setPinsAsOutput:(I)V
       1: invokestatic  #2
       4: iconst_2      
       // Method net/mikekohn/java_grinder/IOPort0.setPortOutputValue:(I)V
       5: invokestatic  #3
       8: iconst_0      
       9: istore_1      
      10: iload_1       
      11: sipush        16384
      14: if_icmpge     23
      17: iinc          1, 1
      20: goto          10
      23: iconst_1      
      // Method net/mikekohn/java_grinder/IOPort0.setPortOutputValue:(I)V
      24: invokestatic  #3
      27: iconst_0      
      28: istore_1      
      29: iload_1       
      30: sipush        16384
      33: if_icmpge     4
      36: iinc          1, 1
      39: goto          29

And the code in out.asm looks like this:

  mov.w SP, r12          <-- need 2 variables: local #0 (function param)
  sub.w #0x4, SP         <-- and local #1 (n) so alloca() 4 bytes
  bis.b #3, &P1DIR       <-- inline function setPinsAsOutput(3)
  mov.b #2, &P1OUT       <-- inline function turns on LED #1
  mov.w #0, -4(r12)      <-- set local variable #1 to 0
  mov.w -4(r12), r4
  cmp.w #16738, r4       <-- check if local variable < 16738
  jge main_23            <-- break if so
  add.w #1, -4(r12)      <-- add 1 to local variable #1
  jmp main_10            <-- run for loop again
  mov.b #1, &P1OUT
  mov.w #0, -4(r12)
  mov.w -4(r12), r4
  cmp.w #16738, r4
  jge main_4
  add.w #1, -4(r12)
  jmp main_29

When running the program looks like this:

Inside Details

So my first step in writing this was to take the source code for naken_java, changed the formatting, and added a generator directory. I started out doing the generator doing some object oriented C using function pointers, and then decided it would probably be better just doing this in C++, so I converted the whole thing to C++.

In the generator directory there is an abstract super-class called Generator that contains all the functions that each architecture must implement (any unimplemented generator function returns -1 to let the compiler (common/compile.cxx) know that this function isn't implemented). In the java directory there is a net/mikekohn/java_grinder directory that have the JavaGrinder API. All classes/methods from this package are implemented in the Generator modules as functions with the name of the class in lowercase, underscore, and the method name unchanged. These functions are called by the functions in the objects/invoke.cxx file.

The flow of the code basically looks like this:

Java Grinder chart

So Java is a stack-based assembly language, in other words if you have a = 3 + 5, Java will push 3 on the stack, then push 5 on the stack, and then with an add instruction pop 3 and 5 off the stack, add them, and put the result back on the stack. To try and avoid using the stack on a microcontroller, which would probably be pretty slow, the generated code uses a "stack" of registers first (r4-r11 on MSP430) and when it runs out it will start using the real stack. This should help the speed of the generated code.


Update November 20, 2015: The Sega Genesis Java demo is done.

Update August 1, 2015: I have Z80 program loading (with audio), pixel plotting, image displaying, and other stuff working on Sega Genesis. More to come.

Update May 20, 2015: I have a simple Sega Genesis program written in Java writting in the MESS emulator. More to come...

Update April 11, 2015: TMS9900 / TI99/4A is now working and I have a YouTube clip of Java running on TI99/4A on this Retro Console Java page.

Update January 2, 2015: I've been kind of eyeballing the Intel Edison and Intel Galileo boards, so yesterday for fun I added x86 and x86_64 files to Java Grinder. I filled in about half of the x86 code. All that's missing is array stuff. Not sure how to do arrays. Should I use the C function malloc()? Or should I use the bss region to create some kind of heap? I put a little sample program in samples/x86 that assembles with The Netwide Assembler (nasm) and links to a C program so it runs on Linux from the command line.

Update October 23, 2014: I have the TMS9900 code mostly written along with part of a TI99 API. Currently it's able to draw text on the screen and even render a Mandelbrot in text mode. I'm adding a higher resolution graphics mode with some plotting routines so a nicer demo can be made. I also need to finish with the array code in the TMS9900.

Update April 6, 2014: I have Z80 code complete along with a little API for the TI84 Plus C calculator, but I haven't figured out how to get a program running in the Tilem emulator yet to make sure it works right. Hopefully soon.

Update March 15, 2014: Joe has been working on optimizing the 6502 code and building the C64 package for his demo. I've also been asked a couple times about a C generator instead of assembly, which to me is kind of odd. Why not just write the code in C and not add another layer? The purpose of Java Grinder is to basically do what a JIT does inside of a JVM, except compile the code before being put onto the flash memory of a micro. A microcontroller wouldn't have enough memory to hold the JIT code anyway. Assembly text seemed like a good idea instead of straight byte code because it makes it easier to bug the assembled code and it takes advantage of naken_asm's features (elf output, label computing, etc). Either way I decided to drop it in quickly anyway just to see what the generated code looks like. It should be working properly except arrays.

Update March 23, 2014: In preparation for Atmel AVR8 support in Java Grinder, I added a simulator for Atmel AVR8 yesterday in naken_asm. Joe will most likely be doing the Java Grinder code for that this week. I'm also adding a simulator for Z80 so Z80 can more easily be added to Java Grinder. I have a TI-84 calculator which would be quite cool to write programs for in Java :).

Update March 4, 2014: Joe Davisson has 6502 working and has a in the testing directory. The demo currently generates a Mandelbrot image. A nice demonstration of Java on the Commodore 64 :).

Update February 10, 2014: I've been adding opimizations to the compiler. Many Java instructions that used to take 2 instructions now take one instruction on the MSP430 which usually saves a cycle or two along with bringing code density down. Also, when using some of Java Grinder's packages, if a constant is passed to the Java Grinder method I was able to avoid putting things on the stack and directly write a literal to the micro's register. This is for both dsPIC and MSP430. More to come :).

Update February 9, 2014: The mul/div/mod instructions are supported in hardware for the dsPIC, but there aren't similar instructions for MSP430. Joe Davisson has now implemented a software version of these instructions so they should work now. He also has plans to add the 65xx code to Java Grinder (since he's the one who wrote the 65xx assembler for naken_asm) so maybe in the near future we'll have Java on the Commodore 64 :).

Copyright 1997-2015 - Michael Kohn