How does `try / catch` work in details
"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.
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.