README

Path: README
Last Update: Tue Oct 17 08:48:29 +0100 2006

RUVA - A toy VM, written in Ruby, that is loosely compatible with the JVM.

RUVA is intended for (my) experimentation and play only. Obviously.

(c)2005-2006 Ross Bamford. Licensed under the Ruby license.

What?

Ruva is a simple stack-based virtual machine implementation written entirely in Ruby. It loosely follows the JVM specification, with the aim of being ‘compatible enough’ to run standard Java(tm) class files (compiled with, for example, Sun‘s javac). Please note, however, that Ruva is not a Java(tm) Virtual Machine, and is not certified or endorsed by Sun Microsystems.

Why?

Why not? I like tinkering with the JVM internals, and I just started playing with this as a tool I could use for tracing individual bytecode operations when debugging methods generated at runtime with Jen (jen.dev.java.net) and ASM (asm.objectweb.org). In time it grew, and got more fun, so I carried on with it a bit at a time, eventually making a start on runtime integration with GNU Classpath and generally getting carried away as usual.

Obviously Ruva is very slow when compared to a real JVM, but then that‘s pretty liberating. I can‘t imagine anyone using a virtual machine written in an interpreted language for real work, so why should it aim for performance at all? Instead, Ruva tries to be very open and very flexible, with everything happening in standard ruby objects as much as possible (e.g. primitives on the stack are ruby Fixnums, Floats and so on).

That said, though, it will probably get a bit quicker as some fairly bad design decisions made early on get fixed ;)

Some of the things I use it for:

  • Tracing execution in buggy generated methods.
  • Figuring out how standard constructs compile and execute.
  • Trying out different opcode implementations.
  • Diagnosing generated classes that won‘t verify.
  • Dumping method code so I can read it.
  • Finding out what life would be like if the JVM were a lot less strict.
  • Learning about Classpath integration

Installation

To install, you can either use Rake

  rake install

or do it manually:

  ruby install.rb

You could also build yourself a Gem if you wanted to:

  rake package

and then install that:

  [su -c ']gem install pkg/ruva-<ver>.gem[']

Ruva requires compiled Java classes from the GNU Classpath project (tested with 0.92), which you can download from www.gnu.org/software/classpath . Follow the instructions to get the classes compiled (you can skip the AWT peers and other native bits, which Ruva cannot support, at the configure stage if you wish).

Once that‘s done, you just need to set an environment variable with the path to the classpath libraries, e.g. (under bash):

  export GNU_CLASSPATH_LIB=/home/rosco/classpath-0.92/lib

You should now be ready to rock n’ roll. A bit.

Usage

If you just want to run some java classes, try the ruva binary. After you‘ve installed, run:

        ruva -h

or read the friendly manpage for usage.

If, on the other hand, you want to play with it from Ruby, you‘ll need to check out the (sparse) API documentation (ruva.rubyforge.org , your installed gem docs, or run `rake doc’) and look through the supplied tests (see also README.tests).

What can it do?

Currently, only a subset of the JVM instruction set is supported, specifically:

  • All primitive xCONST, xLOAD, etc.
  • All primitive arithmetic
  • Some cat1 primitive bitwise operations (xOR, xXOR, etc.)
  • All primitive conditionals
  • All primitive casts
  • All forms of return
  • All stack manipulation (DUP, DUPX1, DUPX2, DUP2, DUP2X1, DUP2X2, SWAP, POP and POP2)
  • In-method branch instructions (JSR(_W), GOTO(_W), RET)
  • Single-dimension arrays of both primitive and reference types (NEWARRAY, ANEWARRAY)
  • All array load/store instructions
  • Object instantiation (NEW)
  • Object-related conditionals (IFNULL, IFNONNULL, IFACMPEQ, IFACMPNE, INSTANCEOF)
  • Static dispatch (INVOKESTATIC)
  • Class dynamic dispatch (INVOKEVIRTUAL, INVOKESPECIAL)
  • Interface dynamic dispatch (INVOKEINTERFACE)
  • Static/instance field get/put
  • Exception throw (ATHROW)

The VM currently has the following general features:

  • VM Bootstrap into any method, VM can return value
  • .class file -> resolved runtime image
  • Dynamic runtime classloading & class pool management
  • Class initializers supported.
  • Per-instruction execution trace
  • Both cat1 and cat2 primitive types supported
  • J5 generic signatures and extra attributes supported
  • ‘Native methods’ (implemented in Ruby!) allow core runtime to be implemented
  • Garbage Collection completely handled by Ruby GC.
  • Exception handling
  • Basic core runtime library integration for Classpath

What can‘t it do?

These things are currently unsupported but will hopefully be implemented:

  • All remaining instructions and their support code:
    • WIDE instructions
    • Primitive unsigned shifts
    • Multi-dimensional arrays
    • TABLESWITCH and LOOKUPSWITCH
  • Runtime annotations (currently read but not unpacked)
  • Threads / monitors
  • More complete core runtime library integration for Classpath:
    • Reflection APIS
    • IO integration
    • etc.

Note that, at present, one area where Classpath integration is lacking is IO, and this prevents even output to the console (via System.out).

The following will probably never be supported:

  • Class verification
  • Security policies and management
  • JNI

[Validate]