Deep analysis of Java try...catch...finally statements

Source: Internet
Author: User
Tags finally block

First, preface

There was a question in the interview some days ago:

 Public class Test {     Public Static void Main (string[] args) {        try  {            return;        }          finally {            System.out.println ("finally ...");}}        }    What is the execution result of the above procedure? 

At that time, I thought the finally block would be executed, and the program was returned in the try block, so I chose the "Compile Error" option, and then I came back to verify that the output was "finally ..." and that the problem was more interesting.

Ii. Analysis of 1. From byte code analysis

In order to better explain the problem, choose a blog example [1] to explain, source code:

 Public classTest {@SuppressWarnings ("Finally")     Public Static Finalstring Test () {string T= ""; Try{T= "Try"; returnT; } Catch(Exception e) {T= "Catch"; returnT; } finally{T= "Finally"; }    }      Public Static voidMain (string[] args) {System.out.print (Test.test ()); }}

According to the general idea, the program executes the TRY statement block, assigns the variable t to try, because no exception is found, then executes the finally statement block, assigns the variable T to finally, then return T, the value of T is finally, and the value of T is Finally, The result of the program should show finally, but the actual result is try. Why this is so, we might as well first look at this code compiled by the class corresponding byte code, see how the virtual machine inside is executed.

We use javap-verbose Test to display the target file (. class file) bytecode information.

System operating Environment: Win7 64-bit

JDK Information: Java version "1.8.0_05", Java (tm) SE Runtime Environment (build 1.8.0_05-b13), Java HotSpot (tm) 64-bit Server VM (buil D 25.5-B02, Mixed mode)

Compiled byte-code part of the information, we only see the test method, the other first ignore:

 Public Static Finaljava.lang.String test (); Descriptor: () Ljava/lang/String; Flags:acc_public, acc_static, acc_final code:stack=1, locals=4, args_size=0 0:ldc #2//String2: Astore_03:LDC #3//String Try5: Astore_06: Aload_07: Astore_18:LDC #4//String finally10: Astore_011: Aload_112: Areturn13: Astore_114:LDC #6//String Catch16: Astore_017: Aload_018: astore_219:LDC #4//String finally21st: Astore_022: Aload_223: Areturn24: Astore_325:LDC #4//String finally27: Astore_028: Aload_329: Athrow Exception table:from to target type3 8 Class java/lang/Exception3 8 24 any13 19 24Any linenumbertable:line5:0 Line8:3 Line9:6 Line14:8 Line10:13 Line11:14 Line12:17 Line14:19stackmaptable:number_of_entries= 2Frame_type= 255/*Full_frame*/Offset_delta= 13Locals= [classjava/lang/String] Stack= [classjava/lang/Exception] Frame_type= 74/*Same_locals_1_stack_item*/Stack= [classJava/lang/throwable]

Observe the Code section:

line [0-2], assign a value to the No. 0 variable "", that is, string t= "";

line [3-5], which is the execution of a TRY statement block assignment statement, that is, T = "Try";

line [6-7], focusing on line 7th, the value of T corresponding to "try" assigned to the 1th variable , but there is no definition of the 1th variable this is more strange;

line [8-10], the No. 0 variable assignment operation, that is t= "finally";

line [11-12], the value corresponding to the 1th variable is returned;

Through bytecode, we know that before return, the virtual opportunity to create an intermediate variable, we can temporarily call T ', and then assign the value of T to T ', then to execute the contents of the finally block, and finally return T ', so even in the finally block modified T, But return returns is T ', so the last output is the contents of T ', as shown in:

2. If a variable object is modified inside a try and finally block
classmyobject{Private intValue = 0;  PublicMyObject (intvalue) {         This. Value =value; }         Public voidSetValue (intvalue) {         This. Value =value; }     Public voidprint () {System.out.println ("Obj:" + This+ ", Value:" +value); }} Public classTest {@SuppressWarnings ("Finally")     Public Static FinalmyObject Test () {MyObject myObj=NULL; Try{MYOBJ=NewMyObject (1); System.out.println ("In Try block");            Myobj.print (); returnMYOBJ; } Catch(Exception e) {myobj.setvalue (2); returnMYOBJ; } finally{Myobj.setvalue (3); }    }      Public Static voidMain (string[] args) {myObject newObj=test (); System.out.println ("After Return");    Newobj.print (); }}

Output:

Try blockobj:[email protected],value:1returnobj:[email protected],value:3

In this example, even though MyObj is assigned to MyObj ', they all point to the same object, so the modification of this object in the finally block is certainly reflected in MyObj '.

3. There are return statements in the try and finally blocks

Or a string example, but the finally statement adds a return statement

 Public classTest {@SuppressWarnings ("Finally")     Public Static Finalstring Test () {string T= ""; Try{T= "Try"; returnT; } Catch(Exception e) {T= "Catch"; returnT; } finally{ T = "finally";
return t;        }    }       Public Static void Main (string[] args) {        System.out.print (test.test ());}    }

Final output:

Finally

In this case, the end is executed and returned directly.

4. The catch statement is executed and there is a return statement
 Public classTest {@SuppressWarnings ("Finally")     Public Static Finalstring Test () {string T= ""; Try{T= "Try"; Integer.parseint (NULL); returnT; } Catch(Exception e) {T= "Catch"; returnT; } finally{T= "Finally"; }    }      Public Static voidMain (string[] args) {System.out.print (Test.test ()); }}

Final output:

Catch

There are cases where intermediate variables are used in both try and catch statements.

5. Exceptions thrown in catch blocks
 Public classTest {@SuppressWarnings ("Finally")     Public Static Finalstring Test () {string T= ""; Try{T= "Try"; Integer.parseint (NULL); returnT; } Catch(Exception e) {T= "Catch"; Integer.parseint (NULL); returnBT; } finally{T= "Finally"; }    }      Public Static voidMain (string[] args) {System.out.print (Test.test ()); }}

Output:

NULL At     java.lang.Integer.parseInt (integer.java:542) at    java.lang.Integer.parseInt (Integer.java :615) at    test.test (test.java:+) at    test.main (Test.java:20)

The execution process is about, executing a try block,integer.parseint (null) statement throws an exception, enters a catch statement, then throws an exception, then executes a finally block, assigns a value to T, Because finally does not return, the catch throws the exception after execution.

If there is a return statement in the finally block, add one more statement "return T;" At the end of the finally block, and the final output:

Finally

6. Throwing Exceptions in finally blocks
 Public classTest {@SuppressWarnings ("Finally")     Public Static Finalstring Test () {string T= ""; Try{T= "Try"; returnT; } Catch(Exception e) {T= "Catch"; returnT; } finally{T= "Finally"; String.valueof (NULL); returnT; }    }      Public Static voidMain (string[] args) {System.out.print (Test.test ()); }}

Output:

Exception in thread "main" java.lang.nullpointerexception[finished in 1.1s with exit code 1] at    java.lang.String. <init> (string.java:166) at    java.lang.String.valueOf (string.java:2993)    at Test.test (Test.java:+) at    test.main (Test.java:20)

Visible execution to a finally block, which causes an exception to terminate the current other operation and throws an exception upwards.

Third, summary
    • In a try,catch,finally statement, if a return statement exists in the Try/catch block, the finally block does not have a return statement, and the Try/catch block produces a temporary variable (t ') that stores the return The variable in the statement (T), if the variable type is a value type or an immutable object, the modification of the variable T in the finally block does not affect the result returned in the Try/catch, and if it is a Mutable object type, the result is affected;
    • If there is a return statement in the finally block, the return statement in the try and catch is ignored;
    • If an exception is thrown in a finally block, the other operations in Try...catch...finally are stopped and the exception is thrown straight up.

Iv. references

1. Detail analysis in Java about try, catch, finally

2. From Java code to byte code (1)

Deep analysis of Java try...catch...finally statements

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.