How does `try / catch` work in details - java

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.

"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.

Lower level method just throws exception and we should handle them in upper level. Consider your example. It should like this
void top() {
try {
f();
} catch (MyException ex) {
handleIt();
} finally {
cleanup();
}
}
void f() throws MyException {
try{
g();
}catch(MyException e){
throws new MyException("Error in g()",e);
}
}
void g() throws MyException{
throw new MyException();
}

Exception are propagated up the call stack, from the method that initially throws it, until a method in the call stack catches it. If a method A calls B, and B calls C then the call stack looks like this:
A
B
C
When method C returns the call stack only contains A and B.
Exception are propagated up the call stack, from the method that initially throws it, until a method in the call stack catches it.
When an exception is thrown the method stops execution right after the "throw" statement. Any statements following the "throw" statement are not executed. The program resumes execution when the exception is caught somewhere by a "catch" block.
If a method calls another method that throws checked exceptions, the calling method is forced to either pass the exception on, or catch it. Catching the exception is done using a try-catch block.If no exception is thrown by any of the methods called or statements executed inside the try-block, the catch-block is simply ignored.If an exception is thrown inside the try-block, for instance from the divide method, the program flow of the calling method, callDivide, is interrupted just like the program flow inside divide. The program flow resumes at a catch-block in the call stack that can catch the thrown exception.
If an exception is thrown inside the catch-block and that exception is not caught, the catch-block is interrupted just like the try-block would have been.
http://tutorials.jenkov.com/java-exception-handling/basic-try-catch-finally.html
https://www.geeksforgeeks.org/flow-control-in-try-catch-finally-in-java/

Related

Why do we need the throw keyword in Java? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
In this answer, the code provided is:
void greet(String name) {
if (name == null) {
throw new IllegalArgumentException("Cannot greet null");
}
System.out.println("Hello, " + name);
}
I have seen similar examples on all sites where I went to learn the 'throw' keyword. What doesn't make sense to me whenever I see such examples is why would one simply not print: "Cannot greet null" instead of throwing an exception.
Questions:
Are there better examples of the utility of the throw keyword? (I am just going to pass out of high school and know only high school level Java programming so please avoid complicated examples)
In the given example, why did the user choose to throw an exception instead of simply printing the error?
Now it is time to revise the concept of Exception Handling in the Java.
First of All what is exception, whenever there is some error or say problem occur while executing the lines of code it is called the Exception.
For Example,
If a person divides something with 0, then it will give an exception as computer cannot handle the undefined entity.
Another example will be while you have declared a Scanner in order to get in integer input, but user enters an alphabet so it will also cause the exception.
Here we do exception handling, which means that we will handle exception in such a way that it will not cause program to close, those specific line which have been enclosed in the try and catch statement will not work properly but other lines will executed.
Now if we have made a method that do something lets suppose prints a line, and there is an exception occurred while printing that line, here we can do two things handle that exception at place where it has occurred or throw it.
If we handle exception at that place it is okay, and if we throw it then we have to catch it place where we have called that method.
Now as there are two types of Exceptions
1) Run Time Exception Which We Call Unchecked Exception
2) Compile Time Exception Which We Call Checked Exception
Both exceptions can be handle at the class level and method level too, one more thing we can do chain exceptional handling too. Which means that one class will throw exception to other and so on.
I think following answer can help you to understand ....
Are there better examples of the utility of the throw keyword?
Basically Throw and Throws are used to prevent the application for getting error or crashing by throwing exception.
Throws are used in the method signature and Throw are used to prevent the flow from getting error.
So here is a simple example for it.
public class Test {
// here we have used "throws" in method signature
// because we are throwing new Exception(), if array is null
public static int getValue(int[] array, int index) throws Exception {
// here we are preventing application from getting
// unconditional error (NullPointer exception)
// if array is null, then we are throwing new Exception()
if(array == null) {
throw new Exception();
}
int value = array[index];
return value;
}
public static void main(String[] args) {
int[] array = null;
// here we are wrapping our getValue() function call to try catch block
// because getValue() function can throws Exception
// so we are making it safe to execute our program
try {
int value = getValue(array, 0);
System.out.println("value " + value);
} catch (Exception e) {
System.out.println("Provided array is null... so we caught the exception...");
}
}
}
if you want to know more about how throw and throws works... then you need to know about Exception Handling (Checked and Unchecked) also.
In the given example, why did the user choose to throw an exception instead of simply printing the error?
As per the given example, your function purpose is to greet, but if some other function call greet() with
null value then there is no any reason to greet like Hello, null, so he throw an exception before executing the statement. like...
void greet(String name) {
System.out.println("Hello, " + name);
}
String myName = null;
greet(myName); // it will print "Hello, null";
'Throw' keyword is used to notify the caller that the argument passed is not valid (in this case), or in general, something went wrong while executing the code called by the caller.
Consider an example where you are writing an online shopping application. Following would be the simple sequence of events:
User scrolls through items and selects one or more items
Items are added into the cart and user clicks check out
User is redirected to 3rd party's payment page where he types in card details and makes the payment
User is shown the success page
Now, during payment, if the card number is incorrect or user doesn't have enough balance in the card, would you throw the error back to the caller (i.e. shopping app) or just log it on the console (on payment provider's side) and return the response? Of course the former, so this is just to let the caller know that there is an error and he should handle it gracefully (by showing appropriate message on checkout in our case).
A throw statement abruptly terminates the execution of the current function, and returns control right back to the caller, forcing them to deal with the error, or rethrow the exception up the chain.
An exception object contains lots of information about where and why an error occurred beyond just the error message. It keeps track of where in the call stack the error happened, and allows you to look up the sequence of calls that led up to it.
A print statement simply could not do all these things. Your example is already a good one. The job of the greet function is to print a greeting. If you pass in null, the function is unable to do so. Printing a message here would be potentially confusing. Instead, it forces you to deal with the fact that you have it invalid input rather than printing a benign message that someone might mistake for a greeting.
Try Java 8 Optional:
String nullVal = null;
System.out.println(Optional.ofNullable(nullVal).orElseGet(() -> null));
String notNull = "Hello Optional";
System.out.println(Optional.ofNullable(notNull).orElseGet(() -> null));
The method can be modify like this:
public static void greet(String name) {
System.out.println("Hello, " + Optional.ofNullable(name).orElseGet(()->null));
}
Assume a function checks that in the passed directory is no malicious file. That could be a void method where you need to catch the exception for the rare case, bypassing the normal processing after the call.
try {
checkDirectorySafe("/home/Donald");
...
} catch (VirusException e) {
...
}
The catch might be late in the code and also catch exceptions in other parts.
There is an other advantage. The function can check all files in the directory and for all subdirectories need only recursively call itself with the subdirectory path. On an exception the call stack is unwound upto the catch.
The Alternative would be to have a boolean or Optional result, and add if code. If the function also needs to return some data, that could become slightly uglier.
An exception is like a toilet in a mall.

IText Constructor not Throwing Exception or Following Flow

I have a static method used to get the title from a PDF using the metadata via itext, which is used as a small part of a major Task.
I noticed an inexplicable path that I narrowed down to this section of code. Specifically, in the line where I instantiate a PdfReader, the process doesn't throw an exception or continue through to the print statement. In fact, it clears out all of my for loops up to the top level of my program and acts as if nothing has happened and my task completed.
try {
System.out.println("Entered method");
PdfReader myReader = new PdfReader(file.getAbsolutePath());
System.out.println("Reader instantiated"); //if no issues, prints to console
Map<String, String> info = myReader.getInfo();
System.out.println(info.get("Title"));
return info.get("Title");
} catch (IOException e) {
System.out.println("PdfReader throws exception"); //if issues, prints to console
e.printStackTrace();
}
Unless I'm mistaken, when this set of code is executed in my method, either "Reader Instantiated" or "PdfReader throws exception" is printed out to the console.
Neither happens. Instead, the process skips every if/for/while loop it is currently in and ends the task.
I'm wondering if someone can explain to me what is happening and how I should go about fixing it?
In the odd event this is searched for, yes, catching Throwable stops the thread from bailing out. I had never seen something like this before. The cause behind the problem was that a PDF was password-protected, so getInfo() failed.

(Java) Thread Inexplicably Stalling at an Exception Catch

I'm stuck in the middle of a real headscratcher here. My program gets to a point where it's supposed to throw an Exception and have it caught by it's parent process, except somewhere in there, the Thread seems to simply stop functioning and I can't explain why.
My program is very complex, but here is the essence of my problem {
public class ClassOne {
public CustomClass computeCustomClass() throws IOException {
//CustomClass is an elsewhere defined valid class in my code.
try {
//The core code of this "computeCustomClass" operation has the
//potential of throwing a "CustomException", an Exception class
//of my own creation.
} catch (CustomException e){
//I have inserted a logging utility here and it is logging that
//this "catch" process is definitely being executed.
//I will now wrap the CustomException in an IOException, as the
//core code of "createCustomClass()" has the potential to generate
//it's own IOExceptions, and the handling of a CustomException should
//be done just the same by a parent process as if an IOException had
//occurred.
throw new IOException(e);
}
}
}
public class ClassTwo {
private ClassOne myObject;
public void processData(){
try{
//I've inserted a logging code here to track when this line is
//executed.
CustomClass data = myObject.computeCustomClass();
//Another bit of logging code goes here and records when the
//"computeCustomClass()" request goes off without a hitch.
// Code goes here that processes the "data" variable;
} catch (IOException e){
//There is logging code here, but it NEVER records this "catch"
//section being executed! Even when the "CustomException" catcher
//in ClassOne.computeCustomClass() is logged as having executed!
//It's as if the thread running this code abruptly stops without
//throwing any exceptions/errors or any indication as to what's
//occurred!
}
}
}
To make matters all the more confusing, I have another thread that runs concurrently to the one that executes the above code. One of this second thread's jobs is to post regular logs about the other thread. Even after whatever occurs that prevents the "catch IOException" code from executing, the thread that SHOULD be executing it reports a "true" value for "isAlive()", and a "false" value for "isInterrupted()".
I don't know what's happening. Any ideas why it might be stalling here, or can somebody suggest a way of diagnosing what the failure actually is?
I see from grepCode that constructing an exception with a cause actually calls the toString() method on the cause.
If your custom exception has a toString() method that could throw an exception or cause some significant time delay then this could be a source of your problem.
You could also - temporarily - use:
//} catch (IOException e){
} catch (Throwable e){
just in case you catch block is being bypassed.

How can I handle user defined exceptions and after handling them resume the flow of program

/**
* An exception thrown when an illegal side pit was
* specified (i.e. not in the range 1-6) for a move
*/
public class IllegalSidePitNumException extends RuntimeException
{
/**
* Exception constructor.
* #param sidePitNum the illegal side pit that was selected.
*/
public IllegalSidePitNumException(int sidePitNum)
{
super("No such side pit number: "+sidePitNum);
}
}
How do I use this in a program and then resume for there? I do not want the program to end but want to handle the exception and continue.
You need to use try/catch. You can learn a lot about exception handling from Sun's (Oracle's) exception handling tutorials. In that tutorial look at the sections about Catching and Handling that specific address your question.
For example, in the code that calls the method that may throw this exception:
try {
...call method here...
} catch (IllegalSidePitNumException e) {
// Display message (per your comment to BalusC)
System.err.println(e.getMessage());
e.printStackTrace(System.err);
// You can also handle the exception other ways (but do not ignore it)
// Such as correcting some offending values, setting up for a retry
// logging the information, throwing a different exception
}
...program continues executing here...
Just catch it.
try {
doStuffWhichPossiblyThrowsThisException();
} catch (IllegalSidePitNumException e) {
// Don't rethrow it. I would however log it.
}
continueWithOtherStuff();
Sidenote: If this is an "expected" exception, you might want to inherit it from Exception instead of RuntimeException. RuntimeExceptions are intended to be used when something unexpected happens, for example illegal input due to a programmer error.
Of course, you don't give the context where you intend to use the exception so this is all theory (but you do mention that you want to continue the execution).
As others have said, you can do the following:
try {
doSomething();
} catch (SomeException ex) {
doRecovery();
}
doSomethingElse();
But there is no way to do something like the following in Java:
doSomething();
throw new SomeException(...);
doSomethingElse(); // ... after some handler has "resumed" the exception.
The above is a (hypothetical) example of "resumption model" exception handling, and Java does not support this. (Nor does C#, C++ or any other currently popular programming language ... though a couple of historical languages did support it.) In fact, the Java compiler will give you a compilation error for the above, saying that the statements after the throw are unreachable.

Java coding practice, runtime exceptions and this scenario

In the following scenario, I was trying to see how to handle this code and it how it relates to Runtimexception. I have read that is generally better to throw runtime exceptions as opposed to rely on static exceptions. And maybe even better to catch a static checked exception and throw an unchecked exception.
Are there any scenarios where it is OK to catch a static exception, possibly the catch-all Exception and just handle the exception. Possibly log an error message and continue on.
In the code below, in the execute1 method and execute2 method, let us say there is volatile code, do you catch the static exception and then rethrow? Or possibly if there are other errors:
if (null == someObj) { throw new RuntimeException(); }
Is this an approach you use?
Pseudo Code:
public class SomeWorkerObject {
private String field1 = "";
private String field2 = "";
public setField1() { }
public setField2() { }
// Do I throw runtime exception here?
public execute1() {
try {
// Do something with field 1
// Do something with field 2
} catch(SomeException) {
throw new RuntimeException();
}
}
// Do I throw runtime exception here?
public execute2() {
try {
// Do something with field 1
// Do something with field 2
} catch(SomeException) {
throw new RuntimeException();
}
}
}
public class TheWeb {
public void processWebRequest() {
SomeWorkerObject obj = new SomeWorkerObject();
obj.setField1("something");
obj.setField2("something");
obj.execute1();
obj.execute2();
// Possibility that runtime exception thrown?
doSomethingWith(obj);
}
}
I have a couple of problems with this code. There are times when I don't want a runtimeexception to be thrown because then execution stops in the calling method. It seems if I trap the errors in the method, maybe I can continue. But I will know if I can continue later on the program.
In the example above, what if obj.execute1() throws a Runtimeexception, then the code exits?
Edited: This guy seems to answer a lot of my questions, but I still want to hear your opinions.
http://misko.hevery.com/2009/09/16/checked-exceptions-i-love-you-but-you-have-to-go/
"Checked exceptions force me to write catch blocks which are meaningless: more code, harder to read, and higher chance that I will mess up the rethrow logic and eat the exception."
When catching an exception and throwing RuntimeException instead, it is important to set the original exception as a cause for the RuntimeException. i.e.
throw new RuntimeException(originalException).
Otherwise you will not know what was the problem in the first place.
Rethrowing checked exceptions as unchecked exceptions should only be done if you are sure that the checked exception is not to be expected.
Here's a typical example:
try {
hash = MessageDigest.getInstance("MD5").digest(string.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
// Unexpected exception. "MD5" is just hardcoded and supported.
throw new RuntimeException("MD5 should be supported?", e);
} catch (UnsupportedEncodingException e) {
// Unexpected exception. "UTF-8" is just hardcoded and supported.
throw new RuntimeException("UTF-8 should be supported?", e);
}
There are times when I don't want a
runtimeexception to be thrown because
then execution stops in the calling
method. It seems if I trap the errors
in the method, maybe I can continue.
But I will know if I can continue
later on the program.
You have the right idea. The advice about throwing RuntimeException is that it doesn't require the caller to use a try-block or a 'throws' clause.
If your code can recover from an exception than it really should catch it and not throw anything.
One of the first rules about exceptions is to not abuse them to pass state in your application. They should be used for exceptional situations, not as alternative return values.
The second rule is to catch exceptions at the level you process them. Catch and rethrow does not add much. Any cleanup code in your method should be done in a finally block.
In my opinion catching checked exceptions and rethrowing them as runtime exceptions is abusing the system. It feels like working around the "limitations" of design by contract instead of using those "limitations" to get a more robust application.
Whether or not to handle an exception or simply rethrow it depends on your use case.
For example, if you're reading a file to load data into your application, and some IO error occurs, you're unlikely to recover from the error, so rethrowing the error to the top and consequently terminating the application isn't a bad course of action.
Conversely, if you're anticipating recoverable errors then you should absolutely catch and handle the errors. For example, you may have users entering data in a form. If they enter data incorrectly, your input processing code may throw an exception (e.g. NumberFormatException when parsing a malformed number string). Your code should catch these exceptions and return an error the user, prompting for correct input.
On an additional note, it's probably bad form to wrap all your exceptions with RuntimeException. If your code is going to be reused somewhere else, it is very helpful to have checked exceptions to signify that your code can fail in certain ways.
For example, assume your code is to parse configuration data from a file. Obviously, an IO error may occur, so you will have to catch an IOException somewhere in your code. You probably won't be able to do anything about the error, so you will have to rethrow it. However, someone calling into your code may well be able to handle such an error, for example by backing off to configuration defaults if the configuration can't be loaded from the file. By marking your API with checked exceptions, someone using your code can clearly see where an error may occur, and can thus write the error handling code at the appropriate place. If instead you simply throw a RuntimeException, the developer using your code won't be aware of possible errors until they creep up during testing.

Categories

Resources