The Artima Developer Community
Sponsored Link

Saying Tomato
A Simulation of the Java Virtual Machine


The Saying Tomato applet, included below, demonstrates a Java virtual machine executing a sequence of bytecodes. This applet accompanies Chapter 16, "Control Flow," of Inside the Java 2 Virtual Machine.

For some reason, your browser won't let you view this way cool Java applet.

The bytecode sequence in the simulation was generated by the javac compiler for the argue() method of the class shown below:

// On CD-ROM in file opcodes/ex1/
class Struggle {

    public final static int TOMAYTO = 0;
    public final static int TOMAHTO = 1;

    static void argue() {

        int say = TOMAYTO;

        for (;;) {

            switch (say) {

            case TOMAYTO:

                say = TOMAHTO;

            case TOMAHTO:

                say = TOMAYTO;

The bytecodes generated by javac for the argue() method are shown here:

 0 iconst_0      // Push constant 0 (TOMAYTO)
 1 istore_0      // Pop into local var 0: int say = TOMAYTO;
 2 iload_0       // Push key for switch from local var 0
                 // Perform switch statement: switch (say) {...
                 // Low case value is 0, high case value is 1
                 // Default branch offset will goto 2
 3 tableswitch 0 to 1: default=2
          0: 24  // case 0 (TOMAYTO): goto 24
          1: 29  // case 1 (TOMAHTO): goto 29
                 // Note that the next instruction starts at address
                 // 24, which means the tableswitch took up 21 bytes
24 iconst_1      // Push constant 1 (TOMAHTO)
25 istore_0      // Pop into local var 0: say = TOMAHTO
26 goto 2        // Branch unconditionally to 2, top of while loop
29 iconst_0      // Push constant 1 (TOMAYTO)
30 istore_0      // Pop into local var 0: say = TOMAYTO
31 goto 2        // Branch unconditionally to 2, top of while loop

The argue() method merely switches the value of say back and forth between TOMAYTO and TOMAHTO. Because the values of TOMAYTO and TOMAHTO were consecutive (TOMAYTO was a 0 and TOMAHTO was a 1), the javac compiler used a tableswitch. The tableswitch is a more efficient instruction than a lookupswitch, and the equivalent lookupswitch instruction would occupy 28 bytes--4 bytes more than tableswitch.

It turns out that even if TOMAYTO were a 0 and TOMAHTO were a 2, the javac compiler still would have used a tableswitch, because even with the extra default branch offset in there for a 1, the tableswitch instruction would occupy only 28 bytes--the same number of bytes as the equivalent lookupswitch. Both instructions occupy the same number of bytes, but tableswitch is more efficient, so it is used. As soon as you make TOMAHTO a 3, however, javac starts using a lookupswitch. This is because a tableswitch would now need two default branch offsets in its list (for 1 and 2), which would push its size up to 32 bytes. Thus, a lookupswitch now would require fewer bytes than a tableswitch--so javac chooses the lookupswitch.

The branch offsets for the case values cause the Java virtual machine to hop down to code that will change the value of the say local variable. The value of say will alternate between TOMAYTO and TOMAHTO indefinitely, until the user aborts the program, thereby calling the whole thing off.

To drive the Saying Tomato simulation, use the Step, Reset, Run, and Stop buttons. Each time you press the Step button, the simulator will execute the instruction pointed to by the pc register. If you press the Run button, the simulation will continue with no further coaxing on your part until you press the Stop button. To start the simulation over, press the Reset button. For each step of the simulation, a panel at the bottom of the applet contains an explanation of what the next instruction will do. Happy clicking.

Click here to view a page of links to the source code of the Saying Tomato applet.

Sponsored Links

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use