Eternal math: a JVM simulation
The applet below simulates a JVM executing a few
bytecode instructions. The instructions in the simulation
were generated by the javac compiler given the following
java code:

The instructions in the simulation represent the body
of the doMathForever() method. These instructions were
chosen because they are a short sequence of bytecodes that
do something mildly interesting on the stack. This
simulation stars the registers, the stack, and the method
area. The heap is not involved in this bytecode sequence,
so it is not shown as part of the applet's user interface.
All numbers in the simulation are shown in hex.

As our story opens, the program counter (pc
register) is pointing to an iconst_0
instruction. The iconst_0 instruction is
in the method area, where bytecodes like to hang out.

When you press the Step button, the JVM will execute
the single instruction that is being pointed to by the
program counter. So, the first time you press the Step
button, the iconst_0 instruction, which
pushes a zero onto the stack, will be executed. After this
instruction has executed,the program counter will be
pointing to the next instruction to execute.Subsequent
presses of the Step button will execute subsequent
instructions and the program counter will lead the way.
Pressing the Reset button will cause the simulation to
start over at the beginning.

The value of each register is shown two ways. The
contents of each register, a 32-bit address, is shown in
hex across the top of the simulation. Additionally,
I put a small pointer to the address contained in
each register next to the address in either the stack or
the method area. The address contained by the program
counter, for example, has a pc> next
to it in the method area.

The Java stack is word-based. Each time something is
pushed onto the Java stack, it goes on as a word (although
longs and doubles actually go on as two words). In the
simulation, the Java stack is shown as an upside-down
tower of words. It is shown growing down the panel (up in
memory addresses) as words are pushed onto it. The stack
recedes back up the panel as words are popped from it. In
this implementation of the JVM, the optop register always
points to the next available slot on the Java stack.

All three sections of the stack frame for the
currently executing method-- the local variables, the
execution environment, and the operand stack -- are shown
in the simulation. Only the local variables and operand
stack take part in this simulation, though. The execution
environment isn't involved in this particular bytecode
sequence, so it is shown filled with zeros.

The local variables section of the Java stack is
treated as an array of words starting at the location
pointed to by the vars register. Bytecodes that deal with
local variables generally include an array index, which is
an offset from the vars register. The address of the nth
local variable is (vars + (n * 4)). You must multiply
n by 4, because each word is 4 bytes long.

The doMathForever() method has only one local
variable, i. It is therefore at array position zero and is
pointed to directly by the vars register. For example,
the iinc instruction takes two byte-sized operands, a
local variable index and an amount. In the simulation,
"iinc 0 1" increments by one the integer at
local variable array position zero. This instruction
implements the "i += 1;" statement from
doMathForever().

With enough patience and clicks of the Step button,
you can get an arithmetic overflow. When the JVM
encounters such a condition, it just truncates, as is
shown by this simulation. No exceptions are thrown.
(Actually, I am just displaying the result of a multiply
operation performed by the "real" JVM in your
browser.)

I put a text description of each step at the bottom of
the applet, which I hope will help to carry you through
the simulation with clarity and deep understanding. Happy
clicking.

When it comes out, the book
The Java Virtual
Machine Specification (http://www.aw.com/cp/lindholm-yellin.html),
by Tim Lindholm and Frank Yellin (ISBN 0-201-63452-X), part of
The Java Series
(http://www.aw.com/cp/javaseries.html), from Addison-Wesley, will likely be
the best JVM resource.

About the author
Bill Venners has been writing software professionally for 12 years.
Based in Silicon Valley, he provides software consulting and training
services under the name Artima
Software Company. Over the years he has developed software for the
consumer electronics, education, semiconductor, and life insurance
industries. He has programmed in many languages on many platforms:
assembly language on various microprocessors, C on Unix, C++ on
Windows, Java on the Web. He is author of the book: Inside the Java
Virtual Machine, published by McGraw-Hill.
Reach Bill at bv@artima.com.