This is the seventh day of my participation in the First Challenge 2022. For details: First Challenge 2022.

Hello everyone, I’m Ah Q!

Let me analyze the execution efficiency of try-catch-finally (TCF) from the perspective of bytecode……

I think it should be the interviewer in the process of the interview to see everyone back of the eight-part essay are the same, feel that there is no need to ask, they turned around to test everyone’s understanding. Today, while brother B is here, we will sum up the knowledge points related to TCF and look forward to a 50-50 discussion with the interviewer next time!

Environment preparation: IntelliJ IDEA 2020.2.3, JDK 1.8.0_181

Execution order

Let’s start with a simple piece of code:

public static int test1(a) {
    int x = 1;
    try {
        return x;
    } finally {
        x = 2; }}Copy the code

The answer is 1, not 2. Are you right?

In TCF, a finally operation is executed first and then a return is returned. Let’s decompile the bytecode file.

Command: javap -v xxx.class

The bytecode instructions are obscure, so let’s illustrate them graphically (let’s look at the first seven lines) : int x = 1;

And then we need to do return x in the try;

At this time, it does not really return the value of X, but stores the value of X in the local variable table as a temporary storage variable for storage, that is, to protect the value.

Finally x=2;

At this point, x has already been assigned 2, but because of the protection operation, the protected temporary storage variable will be pushed onto the stack when the actual return operation is performed.

To better understand the above operation, let’s write a simple piece of code:

public static int test2(a) {
    int x = 1;
    try {
        return x;
    } finally {
        x = 2;
        returnx; }}Copy the code

So let’s think about what is the execution result? The answer is 2, not 1.

Let’s take a look at the bytecode instructions for this program

By comparison, line 6 is iloAD_1 and iloAD_0. What determines this? The reason is that the protection mechanism we mentioned above fails when there is a return statement in finally, and instead pushes the value of the variable onto the stack and returns it.

summary

  • returnThe execution priority of thefinallyThe execution priority of, butreturnInstead of terminating the function immediately after the statement completes, the result is saved toThe stack frameIn theLocal variable scale“, and continuefinallyA statement in a block;
  • iffinallyBlock containsreturnStatement, does nottryBlock to return the value to be protected, instead jumping directly tofinallyStatement, and finally infinallyStatement, the return value is in thefinallyThe value changed in the block;

Do you have a deeper understanding of the TCF execution order? Next we will continue to play TCF. If you have different opinions or better idea, welcome to contact AH Q, add AH Q can also join the technical exchange group to participate in the discussion!