Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does `try / catch` work in details

I would like to the innards of how does try {} catch {} block and stack traces work.

I was reading this great article about exception handling anti-patterns and found the following paragraph:

catch (NoSuchMethodException e) {
  throw new MyServiceException("Blah: " +
      e.getMessage());
}

This destroys the stack trace of the original exception, and is always wrong.

After that I realized that I don't really know how try/catch works. My understanding is the following. Consider the example:

void top() {
    try {
        f();
    } catch (MyException ex) {
        handleIt(); 
    } finally {
        cleanup();
    }
}

void f() {
    g();
}

void g() {
    throw new MyException();
}

When I call top(), the call chain top -> f -> g leaves two stack frames on the call stack (for top and f functions). When the exception is raised in g, the program bubbles up the execution stack until it finds try/catch block that handles the exception. Meanwhile it frees the stack frames and attach stack trace information to some "magic" object that can be passed to catch and the stack trace can be printed.

How does it know that the called function is "surrounded" with the try/catch block? Is this information bound to the stack frame? Like, a pointer to error handling block (some switch selecting a matching catch block), and a pointer to finally block? Why e.getMessage() is destructive in the example above (see the comments)?

Note, I know how to use try/catch and exceptions, I want to know how does it work inside.

like image 641
Jakub M. Avatar asked Nov 04 '13 10:11

Jakub M.


People also ask

How does try catch finally work in Java?

Try block contains the code that might throw an exception. Catch block contains the exception handler for exceptions in the try block. The finally block contains the critical code that will execute regardless of whether the exception has occurred or not.

What is the purpose of a try catch block?

Try/catch blocks allow a program to handle an exception gracefully in the way the programmer wants them to. For example, try/catch blocks will let a program print an error message (rather than simply crash) if it can't find an input file. Try blocks are the first part of try/catch blocks.

Where do you put try catch?

A try catch block is placed around code that could throw an exception. If an exception is thrown, this try catch block will handle the exception to ensure that the application does not cause an unhandled exception, user error, or crash the application.

How does try catch work in C#?

The try-catch statement consists of a try block followed by one or more catch clauses, which specify handlers for different exceptions. When an exception is thrown, the common language runtime (CLR) looks for the catch statement that handles this exception.


2 Answers

"How does it know that the called function is "surrounded" with the try/catch block?"

The code of each method contains Exception Table which describes all try-catch blocks of that method.

When a procedure (function, method) is called, the current stack frame is appended with the address of the calling instruction, so as to restore execution of that frame at the correct instruction (next after calling instruction).

When a throw statement is executed, the JVM examines each stack frame to find out if that frame can handle the exception. It can if its method contains a try-catch block which contains the calling instruction, and the type of block's exception is a supertype (or the same as) of the thrown exception. If such a frame is found, the frame restores its execution from the instruction pointed to from the try-catch block.

like image 56
Alexei Kaigorodov Avatar answered Oct 25 '22 22:10

Alexei Kaigorodov


When an exception is thrown, the complete calling-stack information is attached not to some magic object, but to the exception object that is created. This doesn't happen while the exception "bubbles up" - it happens when it is created and it always contains the full call-chain.

The called function doesn't need to know it is surrounded by a try-catch-block, it just creates an Exception-object that contains the call-chain and passes it up to the calling method. This method has to decide wether it handles the Exception because it is caught by some catch-clause or if it passes it further up. Exception that aren't caught bubble up till they reach the top of the calling-chain and the VM handles them - usually by printing the stack-trace and terminating.

Regarding the e.getMessage-example: The full stack-information is contained only in the original exception. In the given example that original Exception object e is discarded, only the contained message is passed on to a newly created Exception-object. And that Exception only "knows" its own calling stack, so the original information attached to e is lost.

like image 21
piet.t Avatar answered Oct 25 '22 21:10

piet.t