Try catch finally understood by bytecode

Try catch finally understood by bytecode

scene

For the following codes:

public int test() { int x; try { x = 1; return x; } catch (Exception e) { x = 2; return x; } finally { x = 3; } }

I only heard the voice from the mountains:

Back to the stone bank, the trees grow out of the wall.

Who will match the first couplet or the second couplet?

conclusion

  • If there is no Exception belonging to Exception or its subclass in the try statement, the return value is 1
  • If it appears, the return value is 2
  • If there are exceptions other than Exception, the method will not be returned, and the method will exit abnormally

explain

The bytecode obtained through javap is as follows (main part):

This code is by Java Architect must see network-Architecture sorting
public int test(); descriptor: ()I flags: ACC_PUBLIC Code: stack=1, locals=5, args_size=1 0: iconst_1 //Press int type constant 1 into operand stack - > operand stack: 1, local variable table: empty 1: istore_1 / / get the int value out of the stack and store it in the local variable 1 - > operand stack: empty, the local variable table: slot1=1, that is, x=1 2: iload_1 / / load int type values from local variable table 1 and push them into operand stack - > operand stack: 1, local variable table: slot1=1, 3: iStore_ 2 / / get the int value out of the stack and store it in the local variable 2 - > operand stack: empty, local variable table: slot1=1,slot2=1 4: iconst_3 / / press int type constant 3 into operand stack - > operand stack: 3, local variable table: slot1=1, slot2 = 1, 5: iStore_ 1 / / get the int value out of the stack and store it in the local variable 1 - > operand stack: empty, local variable table: slot1=3, slot2 = 1, 6: Iload_ 2 / / load the int type value from the local variable table 2 and push it into the operand stack - > operand stack: 1, local variable table: slot1=3, slot2 = 1, 7: Ireturn / / the int type is returned. At this time, the top of the operand stack is 1, so 1 (no Exception) 8: astore is returned_ 2 / / when an Exception occurs in rows 0 to 3, skip to here, copy the Exception e in catch and store it in the local variable table 2 - > slot2 = e 9: iconst_ 2 / / press int type constant 2 into operand stack - > operand stack: 2, local variable table: slot2=e 10: istore_1 / / get the int value out of the stack and store it in the local variable table 1 - > operand stack: empty, local variable table: slot1=2 11: iload_1 / / load int type values from local variable table 1 and push them into operand stack - > operand stack: 2, local variable table: slot1=2 12: istore_3 / / get the int type value out of the stack and store it in the local variable table 3 - > operand stack: empty, local variable table: slot1=2,slot3=2 13: iconst_3 / / press int type constant 3 into operand stack - > operand stack: 3, local variable table: slot1 = 2, slot3 = 2, 14: iStore_ 1 / / get the int value out of the stack and store it in the local variable table 1 - > operand stack: empty, local variable table: slot1=3, slot3 = 2, 15: Iload_ 3 / / load int type values from local variable table 3 and push them into the operand stack - > operand stack: 2, local variable table: slot1=3, slot3 = 2, 16: Ireturn / / int type is returned. At this time, the top of the operand stack is 2, so 2(Exception condition) 17: astore 4 / / exceptions that do not belong to Exception and its subclasses are stored in local variable table 4 - > local variable table: slot4 = Exception reference 19: iconst_3 / / press int type constant 3 into operand stack - > operand stack: 3, local variable table: slot4 = Exception reference 20: istore_1 / / get the int type value out of the stack and store it in the local variable table 1 - > operand stack: empty, local variable table: slot1=3, slot4 = Exception reference 21: aload 4 / / push the Exception reference in local variable table 4 into the top of the stack 23: arrow / / throw the top Exception table: from to target type 0 4 8 Class java/lang/Exception 0 4 17 any 8 13 17 any 17 19 17 any

Comments are added to each line of bytecode in the above Code to analyze the status of operand stack and local variable table.

Among them, bytecode line numbers 0 to 7 are the bytecode stream when there is no exception, and the return value is 1.

It should be noted that in the above Code, lines 4 and 5 are x=3 in finally. The compiler automatically generates the contents of the finally statement block redundantly after each possible branch path to realize the finally semantics. Similarly, there are lines 13 and 14, lines 19 and 20.

Then let's look at the exception handling table:

Exception table:          from    to  target type              0     4     8   Class java/lang/Exception              0     4    17   any              8    13    17   any             17    19    17   any

It means that in the bytecode line number:

  • If an Exception or its subclass Exception is found in lines 0 to 3, skip to line 8 for processing; If other exceptions are found, skip to line 17 for processing
  • From line 8 to line 12, skip to line 17 for processing
  • The fourth row in the exception table: 17     nineteen     seventeen   any   (I don't understand what it means here. I read the description of the exception table in the virtual machine specification and only said to (that is, end_pc, its exclusivity is a historical design error. Here, the same problem from and target can be supplemented after finding relevant data. It may be that the virtual machine has to read the source code in order to deal with a special situation ~)

Combined with the comments in the Exception table and Code, we can find that if an Exception and its subclass Exception occur in the try statement, the bytecode executed is line 8-16 and the final return value is 2. For other exceptions, skip to line 17 and execute lines 17-23. Finally, the Exception is thrown and the method value is not returned.

Another problem can be found from the exception table. If an exception occurs in the catch block (lines 8 to 12), it will also jump to line 17 for processing, that is, execute the finally code block.

Note: Although the statement x=1 is embodied in the bytecode as iconst and istore, they are still atomic operations. Atomic operations do not mean that there is only one instruction, but one or a series of operations that cannot be interrupted. You can compare the non atomic protocols of long and double.

Reference: deep understanding of Java virtual machine

Posted on Sun, 28 Nov 2021 22:14:11 -0500 by stiano