Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 4
Exception table:
from to target type
0 18 18 any
The bytecodes of the finally clause begin by popping the return address off the stack and storing it into local variable two. At the end of the finally clause, the ret instruction takes its return address from the proper place, local variable two.
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.