Java SE foundation consolidation (XI): Exception

1 What is unusual

Oracle official abnormal gives the following definition:

Definition: An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

Simple translation is an exception in the event a program that appears in the implementation process, it disturbs the normal instruction stream (bad translation, sorry). The program is in the running because of a variety of factors can not continue, for example, can not find the file, the network connection timed out, parses the file failed, etc., Java factors that will cause the program can not be executed properly abstracted into " abnormal ", and thus breakdown variety of" abnormal ", combined with" exception handling "an exception constitute the entire system, the so-called" exception handling "refers to the program when an exception occurs, the program can handle the exception yourself, and attempt to recover an exception so that the program can continue normal operation without the need to think outside intervention. Now I will gradually in-depth introduction to Java exception system in several important points, including, but not limited to:

  • Java exception class inheritance Architecture
  • Unusual classification
  • Exception handling mechanism

In fact, the mechanism of exceptions and exception handling mechanisms have on the computer hardware, various programming languages ​​do its abstraction, making the detection of abnormal process more convenient and efficient.

2 Java exception class inherits architecture

iNBBoq.png

The figure is a configuration diagram of Java exception class, can be seen from FIG Throwable exception class is the parent of the entire system, it has two major subclasses, respectively, and Error Exception.

2.1 Exception

Exception That exception is the application itself can handle, Java will be divided into two categories:

  • Unchecked exceptions. Exceptions Exceptions can be understood as that happens runtime runtime, this type of exception must not force the program to capture or throw, do not recommend actually very unusual, because the runtime exceptions often refer to capture the program run time some kind of system abnormalities, difficult to handle, if caught is also likely to cause the program not to print error stack, making it difficult to troubleshoot the error.
  • Unchecked exceptions. In addition to RuntimeException and its subclasses, other subjects are Exception abnormal, Java compiler requires that procedures must capture (depending on whether the processing requirements) or in the method signature throws plus the type of statement throws an exception.

2.2 Error

Error That is wrong, because Error is often related to virtual machines more serious error, the application is generally no ability to recover, for example StackOverflowError (stack overflow), OutOfMemoryError (out of memory) and other virtual machines on this the wrong approach in general stop is directly associated thread (that is, if the application is multi-threaded program, even if there has been Error, applications are likely not to exit). In fact, Java applications, although not prohibit the capture Error, but we should also try not to do it, because this program logic errors are not errors, but the virtual machine error occurs, basically can not be repaired, if captured but we can not handle it, we will not get the wrong stack, making it difficult to troubleshoot the problem.

3 exception handling mechanism

Java exception handling mechanism comprises three aspects: detecting an abnormality, and catch the exception handling exceptions.

3.1 try-catch block detection, capture and handle exceptions

We can try using keyword to specify a range that is the anomaly detection range, and then use the catch block to create an exception handler (in Java, only try if you can not pass without a catch compile) Consider the following code:

public static void method1() {
    try {
        method2();
    } catch (IOException e) {
        System.out.println("catch io exception");
    }
}
复制代码

First with javac to compile, then javap -verbose XXX.class translate bytecode information and print out the results as follows:

  public static void method1() throws java.io.IOException;
    descriptor: ()V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=1, args_size=0
         0: invokestatic  #6                  // Method method2:()V
         3: goto          15
         6: astore_0
         7: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        10: ldc           #8                  // String catch io exception
        12: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        15: return
      Exception table:                          //异常表
         from    to  target type
             0     3     6   Class java/io/IOException   
      LineNumberTable:
        line 19: 0
        line 22: 3
        line 20: 6
        line 21: 7
        line 23: 15
      StackMapTable: number_of_entries = 2
        frame_type = 70 /* same_locals_1_stack_item */
          stack = [ class java/io/IOException ]
        frame_type = 8 /* same */
复制代码

Mainly to see Exception table (that is, the exception table) label, found that only one line of data, there are from, to, target, type and other fields. from, to constitute an anomaly detection range (i.e. example 0-3), on behalf of the bytecode exception handling target based index (i.e. example 6 of byte code index), represents a type of exception handling processor exception type (an example is IOException).

Now look Exception table (exception table), the abnormality data table row represent an exception handler, each row there from, to, target, type four fields, the value of the first three fields are bytecode index, is a value of the type of reference symbol indicating the type of exception handling processor. Each method will have an exception table, but sometimes we do not see in print the results of javap, this is because there is no corresponding exception handler method, namely the exception table does not have any data, but it javap omitted it.

When an exception occurs, the virtual opportunity to traverse the exception table, first check whether the abnormal position of the detection range of an entry (from-to field) in the exception table, if there is such an entry, will continue to check the toss whether the abnormality is an abnormality of matches and type fields described, if the match, jump to the target value pointed to bytecode exception handling. If you traverse the complete table but could not find matching rows, it will pop the stack, and continue as operations on the stack frame at this time, the worst case is the virtual machine needs to traverse the entire method call stack all of the exception table, If the last match is no exception table entry is found, the virtual machine directly to an exception is thrown, and print exception stack information.

The text above description may be a bit around, do not worry, look at this logic flow chart below, combined with text descriptions, should be able to understand the process of exception handling.

iUKU2V.png

In fact, from the process described above, it is also an important implicit knowledge: exception propagation mechanism . That is, when the current method can not handle, an exception will be propagated to the caller, continue to try to handle exceptions, and so forth, knows the top level of the caller, or if no suitable exception handling, then stopped directly thread exception is thrown and prints abnormal stack. The following code demonstrates the anomalous propagation mechanism:

public class Main {

    public static void main(String[] args) {
        method1();

        System.out.println("continue...");
    }

    public static void method1() {
        try {
            method2();
        } catch (IOException e) {
            System.out.println("catch io exception");
        }
    }

    public static void method2() throws IOException{
        method3();
    }

    public static void method3() throws IOException {
        throw new IOException("method3");
    }

}

复制代码

Code, main method calls method1, method1 calls method2, method2 call method3, throw in a IOEception method3 because a subject is abnormal IOException, so method2 either use try-catch construct an exception handler, or use key throws the word abnormal continue throwing up, method2 choice is up to throw an exception, method1 is constructed an exception handler, if the exception handler can correctly capture and handle exceptions, it will not go down to throw an exception on the , so the main method does not require special treatment. Run, the results shown as follows:

catch io exception
continue...
复制代码

Correctly found that continue output, the main thread is not stopped, that is an exception has been handled correctly. Now modify the code as follows:

public static void method1() throws IOException {
    method2();
}
//其他部分代码没有变化
复制代码

At this time run again, the results as follows:

Exception in thread "main" java.io.IOException: method3
	at top.yeonon.exception.Main.method3(Main.java:26)
	at top.yeonon.exception.Main.method2(Main.java:22)
	at top.yeonon.exception.Main.method1(Main.java:18)
	at top.yeonon.exception.Main.main(Main.java:12)
复制代码

I found a print exception stack, but do not print continue, explained the main thread and the virtual machine is stopped, could not continue. This is because in the method call stack, the exception table not found a matching entry in the exception table any method that does not find a suitable exception handler, ultimately there is no way but to stop the thread and throw exceptions, count on the program members can deal with.

3.2 finally

Until now, I did not mention finally, but in fact finally also a very important component. finally try-catch block may be combined, whether abnormality will be executed in the logic finally occurs. finally it is designed to avoid the programmer forgot to write some code cleanup operations, such as turning off network connections, file IO connections.

Compile finally block is relatively complex, the compiler (the current version of the compiler) not to realize the function "exception will be executed finally whether or not occur," the direct use of jump instructions. Instead of using the method "copy", copy the code blocks to finally try-catch block performs all of the normal position and the outlet path abnormality execution path. As shown below (Figure geeks from the time a course on the JVM, in the end I will be marked):

iUQ1ts.png

1 variant 2 variant and logic is actually the same, only the location where the finally block just not the same. Now suppose the following code:

public class Main {

    public static void main(String[] args) {
        try {
            method3();
        } catch (IOException e) {
            System.out.println("catch io exception");
        } finally {
            System.out.println("execute finally block");
        }
        System.out.println("continue...");
    }

    public static void method3() throws IOException {
        throw new IOException("method3");
    }
}

复制代码

Also after compilation, the output can be used to read javap byte code, as follows:

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: invokestatic  #2                  // Method method3:()V
         3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         6: ldc           #4                  // String execute finally block
         8: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        11: goto          45
        14: astore_1
        15: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        18: ldc           #7                  // String catch io exception
        20: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        23: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        26: ldc           #4                  // String execute finally block
        28: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        31: goto          45
        34: astore_2
        35: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        38: ldc           #4                  // String execute finally block
        40: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        43: aload_2
        44: athrow
        45: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
        48: ldc           #8                  // String continue...
        50: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        53: return
      Exception table:
         from    to  target type
             0     3    14   Class java/io/IOException
             0     3    34   any
            14    23    34   any
复制代码

6,26,38 note numbers before and after the two instructions and instruction, in fact, found that the content of a finally block codes, i.e. string output execute finally block. And exactly 3 parts, are known and previously described. Then take a look at the exception table, look at the focus back two rows, here is the special type of field, the field's value is any, javap used to refer to all of this is that all abnormal abnormality that these two entries to be processed. Wherein the first range of form-to from 0 to 3, was found to range try block, the second range is from-to 14 to 23, in fact, found that catch block. Why is this so?

First, let me try block, for example, where the number 34 if the exception handler can not define our own and unusual match occurs, then it will be the exception handler to catch all exceptions capture, and jump to the location where the exception handler, instruction, we find that in fact is the location of the original Directive No. 34 where the finally block, that is to say, even if found not caught exception, will finally come to the logical block. For normal circumstances, it is not come starting block number 34, but directly goto (instruction 11) to 45 instruction.

Catch block is then, as in the catch block may also occurrence of an abnormality, so that such an exception trap plus, and Same as above, execution jumps to the finally instruction at 34, if no abnormality occurs in the catch block , and where the same try block, the code continues finally copied blocks, after the implementation of direct goto (instruction 31) to an instruction at 45, and finally the last block is not performed from the beginning of the 34.

This is why the entire try-catch-finally structure, regardless of whether an exception occurs, will always be executed finally in logic.

4 Summary

This paper introduces the concept of exceptions, classification and exception handling mechanism. In particular exception handling mechanism, we go deep into the bytecode level view execution flow of the entire processing mechanism, we believe we will Exception Handling deeper understanding. finally also a very important component, its role is in the whole try-catch-finally structure, regardless of whether an exception occurs, the finally block will be executed in the logic, and I also try to analyze deep into byte code is how to achieve this function of.

5 References

In-depth understanding of java exception handling mechanism

Time Geeks: in-depth Java Virtual Machine dismantling Section 6: JVM is how to handle exceptions?

Guess you like

Origin juejin.im/post/5d6e80905188251b764b5cb8