The Artima Developer Community
Sponsored Link

Hop Around
A Simulation of the Java Virtual Machine

Advertisement

The Hop Around applet, included below, demonstrates a Java virtual machine executing a sequence of bytecodes. This applet accompanies Chapter 18, "Finally Clauses," 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 hopAround() method of the class shown below:

// On CD-ROM in file opcodes/ex1/Clown.java
class Clown {

    static int hopAround() {
        int i = 0;
        while (true) {
            try {
                try {
                    i = 1;
                }
                finally {  // The first finally clause
                    i = 2;
                }
                i = 3;
                // This return never completes, because of
                // the continue in the second finally clause
                return i;
            }
            finally {      // The second finally clause
                if (i == 3) {
                     // This continue overrides the return statement
                    continue;
                }
            }
        }
    }
}

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

 0 iconst_0      // Push constant 0
 1 istore_0      // Pop into local var 0: int i = 0;

// Both try blocks start here (see exception table, below):
 2 iconst_1      // Push constant 1
 3 istore_0      // Pop into local var 0: i = 1;
 4 jsr 18        // Jump to mini-subroutine at offset 18 (the
                 // first finally clause)
 7 goto 24       // Jump to offset 24 (to just below first
                 // finally clause)

// Catch clause for the first finally clause:
10 astore 4      // Pop the reference to thrown exception, store
                 // in local variable 4
12 jsr 18        // Jump to mini-subroutine at offset 18 (the
                 // first finally clause)
15 aload 4       // Push the reference (to thrown exception)
                 // from local variable 4
17 athrow        // Rethrow the same exception

// The first finally clause:
18 astore 5      // Store the return address in local variable 5
20 iconst_2      // Push constant 2
21 istore_0      // Pop into local var 0: i = 2;
22 ret 5         // Jump to return address stored in local variable 5

// Bytecodes for the code just after the first finally clause:
24 iconst_3      // Push constant 3
25 istore_0      // Pop into local var 0: int i = 3;

// Bytecodes for the return statment:
26 iload_0       // Push the int from local
                 // variable 0 (i, which is 3)
27 istore_1      // Pop and store the int into local
                 // variable 1 (the return value, i)
28 jsr 39        // Jump to mini-subroutine at offset 39 (the
                 // second finally clause)
31 iload_1       // Push the int from local variable 1 (the
                 // return value)
32 ireturn       // Return the int on the top of the stack

// Catch clause for the second finally clause:
33 astore_2      // Pop the reference to thrown exception, store
                 // in local variable 2
34 jsr 39        // Jump to mini-subroutine at offset 39 (the
                 // second finally clause)
37 aload_2       // Push the reference (to thrown exception)
                 // from local variable 2
38 athrow        // Rethrow the same exception

// The second finally clause:
39 astore_3      // Store the return address in local variable 3
40 iload_0       // Push the int from local variable 0 (i)
41 iconst_3      // Push constant 3
42 if_icmpeq 47  // If the top two ints on the stack are equal, jump
                 // to offset 47: if (i == 3) {
45 ret 3         // Jump to return address stored in local variable 3
47 goto 2        // Jump to offset 2 (the top of the while
                 // block): continue;

Exception table:
   from   to  target type
     2     4    10   any
     2    31    31   any

The hopAround() method returns from the first finally clause by executing past the closing curly brace, but returns from the second finally clause by executing a continue statement. The first finally clause, therefore, exits via its ret instruction. But because the second finally clause exits via a continue, its ret instruction is never executed. The continue statement causes the Java virtual machine to jump to the top of the while loop again. This results in an endless loop, even though it is a return statement that originally causes the second finally clause to be executed in the first place. The continue statement in the finally clause supersedes the return statement, so the method never returns.

Note that the bytecodes that implement the return statement store a copy of the return value into local variable one before jumping to the miniature subroutine that represents the second finally clause. Then, after the miniature subroutine returns (in this case it never does, because the continue is always executed), the return value is retrieved from local variable one and returned.

This highlights the way the Java virtual machine returns values when finally clauses are also executed. Rather than returning the value of i after the finally clause is executed, the Java virtual machine will return the value that i had just before the finally clause was executed. This means that even if the finally clause changes the value of i, the method will still return the value that i had when the return statement was first reached, before the finally clause was invoked. If you wanted the finally clause to be able to change the return value of the method, you would have to put an actual return statement with the new return value into the finally clause itself.

To drive the Hop Around 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 Hop Around applet.


Sponsored Links



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