The Artima Developer Community
Sponsored Link

Try-finally Clauses Defined and Demonstrated
Java Bytecodes that Deal with Finally Clauses
by Bill Venners
First Published in JavaWorld, February 1997

<<  Page 3 of 3

Advertisement

HopAround: A Java virtual machine simulation
The applet below demonstrates a Java virtual machine executing a sequence of bytecodes. The bytecode sequence in the simulation was generated by the javac compiler for the hopAround() method of the class shown below:

class Clown {

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

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

   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 16 // Jump to mini-subroutine at offset 16 (the first finally clause)
   7 goto 22 // Jump to offset 22 (to just below first finally clause)

                          // Catch clause for the first finally clause:
  10 astore_3 // Pop the reference to thrown exception, store in local variable 3
  11 jsr 16 // Jump to mini-subroutine at offset 16 (the first finally clause)
  14 aload_3 // Push the reference (to thrown exception) from local variable 3
  15 athrow // Rethrow the same exception

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

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

                          // Bytecodes for the return statment:
  24 iload_0 // Push the int from local variable 0 (i, which is 3)
  25 istore_3 // Pop and store the int into local variable 3 (the return value, i)
  26 jsr 37 // Jump to mini-subroutine at offset 37 (the second finally clause)
  29 iload_3 // Push the int from local variable 3 (the return value)
  30 ireturn // Return the int on the top of the stack

                          // Catch clause for the second finally clause:
  31 astore_1 // Pop the reference to thrown exception, store in local variable 1
  32 jsr 37 // Jump to mini-subroutine at offset 37 (the second finally clause)
  35 aload_1 // Push the reference (to thrown exception) from local variable 1
  36 athrow // Rethrow the same exception

                          // The second finally clause:
  37 astore_2 // Store the return address in local variable 2
  38 iload_0 // Push the int from local variable 0 (i)
  39 iconst_3 // Push constant 3
  40 if_icmpne 46 // If the top two ints on the stack are unequal, jump to offset 46: if (i == 3) {
  43 goto 2 // Jump to offset 2 (the top of the while block): continue;
  46 ret 2 // Jump to return address stored in local variable 2

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 JVM 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 3 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 3 and returned. This highlights the way the JVM returns values when finally clauses are also executed. Rather than returning the value of i after the finally clause is executed, the JVM 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 simulation, just press the Step button. Each press of the Step button will cause the Java virtual machine to execute one bytecode instruction. To start the simulation over, press the Reset button. To cause the Java virtual machine to repeatedly execute bytecodes with no further coaxing on your part, press the Run button. The Java virtual machine will then execute the bytecodes until the Stop button is pressed. The text area at the bottom of the applet describes the next instruction to be executed. Happy clicking.

Resources

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. You can reach him at bv@artima.com.

This article was first published under the name Under the Hood: Try-finally clauses defined and demonstrated in JavaWorld, a division of Web Publishing, Inc., February 1997.

<<  Page 3 of 3


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us