Before we answer the question of the title, let’s imagine that without try… In the catch case, what should we do if we want to judge the abnormal result of a function?
abnormal
The first thought must be if… Else, under normal circumstances, the relevant code we are together, if your program at this time have a lot of code to do this in the judgment, which means that perform logic behind will rely on you in front of the above statement, which means you call each may appear error function, must first determine whether success, Then proceed with the following statement. This can lead to a lot of if… The else. Java is an engineering language, and engineering is an art, so this approach is decidedly inelegant. Thinking in Java mentions “badly formed code will not be run.” This means that badly formed code should not be executed, so a Java-appropriate exception handling mechanism was created. Java’s exception handling is designed to simplify large programs by using less code than they currently do. A simple example is 🌰 instead of trying… catch
FileReader fr = new FileReader("path");
if (fr == null) {
System.err.println("Open File Error");
} else {
BufferedReader br = new BufferedReader(fr);
while (br.ready()) {
String line = br.readLine();
if (line == null) {
System.err.println("Read Line Error");
} else{ System.out.println(line); }}}Copy the code
Using a try… catch
try {
FileReader fr = new FileReader("path");
BufferedReader br = new BufferedReader(fr);
while(br.ready()) { String line = br.readLine(); System.out.println(line); }}catch (IOException e) {
e.printStackTrace();
}
Copy the code
Obviously, we can see that the following way of writing is more clear and readable. Of course, try… A catch is not a bad thing. If programmers abuse try in their code… Catch, and poor exception handling may result in bugs being hidden and untraceable. But that’s not the focus of this article. For those interested, check out Chapter 12 of Thinking in Java, “Handling Errors through Exceptions.”
Catch exceptions separately
Before exploring the combination of exception catching and looping, let’s take a look at what happens when an exception is caught alone. This is an exception codeWe usejavap -c ExceptionDemo.class
Let’s print out his bytecode and take a lookThe meaning of instructions is not the focus of this article, so I will not introduce the specific meaning here. If you are interested, you can go to the Oracle official website to check the meaning of the corresponding instructions 👉The Java Virtual Machine Instruction Set
Four parameters of the exception table
From the output, the bytecode is divided into two parts, code and exception table. When the Java source code is compiled into the corresponding bytecode, if a method has a try catch exception handler, the exception table associated with that method is generated, i.eException table:
Part. Each entry hasFour column information: The start line of the exception declaration, the end line, the number of lines pointed to by the code counter (PC) to which the exception is jumped after being caught, and a constant pool index representing the caught exception class. So where did you get this information? Here’s a refresher on the JVM:A thread is a stack, composed of stack frames, a method is a stack frame, internal storage: local variable table, operand stack, dynamic link, method exit. The JVM needs to generate the stack trace of an exception when constructing an exception instance. This operation accesses the stack frames of the current thread one by one and records various debugging information, including the name of the method to which the stack frame points, the class name of the method, the file name, and the line in the code at which the exception was raised. And that information will be stored in what we just saidException table:
In the.
The role of the four parameters
So what’s the use of all that information? If an exception is thrown during the execution of a method, the JVM looks up items from the exception table in the order in which they appear. If the number of rows that the PC counter points to falls within the range of an entry in the exception table when the exception is thrown, and the exception that is thrown happens to be the exception specified in the type column of the exception table (or a subclass of the exception specified), then the JVM points the PC counter to the address indicated by the Target offset. (Enter catch block) continue execution. If no exception is found in the exception table, the JVM ejects the current stack frame and rethrows the exception. When the JVM pops the current stack frame, it aborts execution of the current method and returns to the external method that called the current method, but instead of continuing execution of the external method as it would normally if no exception had occurred, it throws the same exception in the external method. This causes the JVM to repeatedly query the exception table and handle exceptions in external methods.
Why does catching exceptions cost performance
When you create a new exception, the JVM has already built all the stackTrace in the exception:One of the most popular frameworks in the Java space right now is the Spring family. In a Web project, the depth of the call stack is quite large, which can be quite costly, so when you don’t need this information when you’re not interested in StackTrace, It’s best not to make random new exceptions.
Exception +for loop
Having said all that, it’s all pre-knowledge, and now we finally come to the question mentioned in the title. There are two ways for loops and exceptions can be combined: try+for loops
public static void tryFor(a) {
int j = 3;
try {
for (int i = 0; i < 1000; i++) { Math.sin(j); }}catch(Exception e) { e.printStackTrace(); }}Copy the code
The for loop + a try
public static void forTry(a) {
int j = 3;
for (int i = 0; i < 1000; i++) {
try {
Math.sin(j);
} catch(Exception e) { e.printStackTrace(); }}}Copy the code
Let me start by concluding that there is no difference in performance when no exceptions occur. If an exception occurs, the processing logic of the two is different. Although the comparison is not meaningful, the time of the for loop +try is more obvious.
Bytecode comparison
Let’s do a bytecode comparison of these two approaches:Through analysis we know that in the second quarter, when the program is abnormal, the Java virtual machine will be corresponding exception table lookup method, if find any statement of exception and thrown exception types match will jump to catch executes the corresponding logic, if no match is successful, will be back to the upper call methods continue to search, so again and again, Until the exception is handled, or the process is stopped. Instead, try in the for loop… The catch operation is constantly doing this, and the performance loss is naturally horrible.
The test is
Said so much we have been on paper, talk without proof, the actual effect is certainly to run to know, here we use a Java microbenchmark framework JMH to carry out this test. The test results
Benchmark Mode Cnt Score Error Units
ExceptionDemo.forTry thrpt 20 70.236 ± 8.945 ops/ms
ExceptionDemo.tryFor thrpt 20 85.864 ± 3.272 ops/ms
Copy the code
Score results in XXX ± XXX, in units of operations per millisecond. The final results also confirm our conclusion. TryFor does save more performance than forTry.
The last
Starting with exceptions, this article looked at several different cases of catching exceptions alone and combining exceptions with for loops, and then ran a test with JMH to finally verify our title that catching exceptions in for loops is not recommended. Of course, try… In addition to the need to maintain an exception list mentioned in section 2, the reason for the performance impact of a catch is that try blocks prevent Java optimizations (such as reordering), and the code inside a try catch is not reordered by the compiler optimizations. Of course, reorder is triggered by certain conditions. In general, the smaller the scope of the try block, the less impact it has on Java’s optimization mechanism. So ensuring that the scope of the try block only covers where exceptions are thrown minimizes the impact of exceptions on Java optimization mechanisms. That’s all for this article. If you found it helpful, please give it a thumbs up.