Why a stacktrace of an exception is printed at last? - java

Here is my simple test code:
class Scratch {
public static void main(String[] args) {
try {
System.out.println("Line 1");
throw new RuntimeException();
} catch (RuntimeException e) {
e.printStackTrace();
} finally {
System.out.println("Line 2");
}
}
}
After running I'll get this:
Line 1
Line 2
java.lang.RuntimeException
at Scratch.main(scratch_4.java:5)
Process finished with exit code 0
I thought that "finally" code must be executed at last, but it's not.
What is the reason?

By default, printStackTrace prints to System.err, whereas you're writing to System.out. So you're writing to two different streams, and in your particular case it looks like the buffering involved has switched the output order from the actual execution order.
If you either write to a single stream (e.g. using System.err.println or calling e.printStackTrace(System.out)) or change your catch block to just write to System.out like your other lines do, you'll see the order of try => catch => finally.

Related

In Java catch block, how do you know which method/line throws the exception?

In try block, I want to execute two functions. If the first one failed then don't execute the second. I also want to print out which function failed.
See following code.
try {
a = func1();
b = func2(); //won't execute if a failed
}
catch (Exception e) {
//TODO: print a or b failed?
}
Does the language support this scenario naturally?
If not, is the following a good practice? (I cannot think of anything wrong about it. But it concerns me as I don't remember seeing any one using return in catch.)
try {
a = func1();
}
catch {
//print: a failed
return; //if a failed then skip the execution of b
}
try {
b = func2();
}
catch {
//print: b failed
}
EDIT:
Summary of comments:
throw different exception from two methods.
In this case the methods are written by others and I have no control.
e.printStackTrace() will print line number and function
I want to do more than just printing. More like, if a failed, execute the following code.
What you want is String methodName = e.getStackTrace()[0].getMethodName());
But this is hardly a good practice. The standard way is to log the exception using appropriate method in your logging framework or (if writing a console app, which is rarely the case with Java) to print it to the error or standard output or optionally to other PrintStream, for example using printStackTrace(printStream).
But in most cases you want to propagate exception to the upper layers and handle (or decide to not handle it) by the appropriate high level code. Catching exceptions like this leads to nasty bugs. Returning from catch black is also a very bad idea in 99% of cases because exception signalizes abnormal termination of the method while returning a value does not.
As dev-null wrote e.getStackTrace() can help. But note that the exception may not be thrown by func1 or func2 themselves but by some other method they call. So you need to go through all elements of the array until you hit func1 or func2.
Calling them in separate try blocks is definitely practiced but it can get cumbersome.
Logging the stack trace if an exception is thrown will inform you which line threw the exception. If the first line in the try/catch throws the exception, the next line will not be executed.
This will work:
String failedFunc = "func1";
try {
a = func1();
failedFunc = "func2";
b = func2(); //won't execute if func1() failed
} catch (Exception e) {
System.out.println("Func '" + failedFunc + "' failed: " + e);
}
Or course, if all you're doing is printing the error, then printing the stack trace will show you exactly where it failed. The above code is however useful if you need the value of failedFunc without a full stack trace.
As I said in the comments, you can use e.printStackTrace() to determine the cause of the Exception. Since you expressed a desire for different behaviors then you have a few options. You could write two local functions to decorate your func1 and func2 calls with custom Exceptions. Something like,
class Func1Exception extends Exception {
public Func1Exception(Exception e) {
super(e);
}
}
class Func2Exception extends Exception {
public Func2Exception(Exception e) {
super(e);
}
}
Then you can write the local functions like
private static Object func1Decorator() throws Func1Exception {
try {
return func1();
} catch (Exception e) {
throw new Func1Exception(e);
}
}
private static Object func2Decorator() throws Func2Exception {
try {
return func2();
} catch (Exception e) {
throw new Func2Exception(e);
}
}
Then you can handle them however you wish,
try {
a = func1Decorator();
b = func2Decorator(); // this still won't execute if a failed
} catch (Func1Exception e) {
// a failed.
} catch (Func2Exception e) {
// b failed.
}
If you want func2 to run even when a fails you could use a finally block,
try {
a = func1Decorator();
} catch (Func1Exception e) {
// a failed.
} finally {
try {
b = func2Decorator(); // this will execute if a fails
} catch (Func2Exception e) {
// b failed.
}
}

Resume code in try block after exception is caught

I am fairly new to using try/catch blocks, so I don't know how exactly to perform this command.
If I catch an error, I would like to wait a period of time(10 seconds or so) then try to run the same line of code to attempt to continue in my try block. My program is written in Java. I have looked at both these pages: Page1, Page2, but neither of them are in Java. I have also looked at this, but they are not solving in the using the catch block. Is this possible to do, and how would I implement this in my catch block instead of just printing the error?
99% of time, you want to re-run a code-block after a try-catch and not the line with exception.
If you need to run from that line, than that is an indication for you to take your code in another method that encapsulates only that code (maybe move the try-catch there too).
What i would advice is something like this:
void method(){
try{
codeline1;
codeline2;
codeline3;
codeline4;
}
catch(Exception ex)
{
restorClassStateBeforeCodeLine1();
method();
}
}
By that snipped i propose to have your entire try-catch in a separate method.
Waiting random intervals is bad practice also. You never know if 10 seconds is right every time or at all.
Another way that I advise against would be:
label: {
try {
...
if (condition)
break label;
...
} catch (Exception e) {
...
}
}
It uses java labels to retry that part. I never tried but the break could be moved in the catch and the label in the try.
I don't think it is possible to return to a certain line in your try-block from inside a catch-block. Because when the throwis executed, the runtime system is going to pop frames from the call stack, looking for an exception handler to match the thrown exception and once the frame is popped from the stack, it's gone. More info about this can be found here
What you can do is call the method that caused the throw from within the catch-block. But that means it is going to execute your method from the beginning, so maybe you want to try to rearrange your code so that this does not cause any other problems. EDIT: The other answer demonstrates exactly what I mean.
This simple program loops through array values, testing each until it finds a value that doesn't generate an exception
public static void main(String[] args) {
int[] array=new int[]{0,0,0,0,5};
for(int i=0; i<array.length;i++) {
try {
System.out.println(10/array[i]);
break;
} catch(Exception e) {
try { Thread.sleep(1000); } catch(Exception ignore){}
}
}
}
while(true){
try{
//actions where some exception can be thrown
break;//executed when no exceptions appeared only
}
catch(YourException e){
Thread.sleep(10_000);
}
}
This cycle will be repeated while you instructions haven't executed. When code in try-block executed succesfully break helps you leave this cycle
Since you are saying that it is only 2 lines of code that you experience the intermittent error with, try something similar to this.
public static void main(String... args)
{
try
{
//Some Logic
//Error throwing logic in method
while(!doLogic())
{
Thread.sleep(1000);//Sleep here or in doLogic catch
}
//Continuing other logic!
}
catch(Exception e)
{
e.printStackTrace();
}
}
static Integer i = null;
public static boolean doLogic()
{
try
{
//Lines that throw error
System.out.println(i.toString());//NPE First run
}
catch (Exception e)
{
i = 1;
return false;
}
return true;
}

Java - exception handling and force full exit from the system

Please excuse me for this kind of questions here but I am sure to get good explanation with sample which will make to have better understanding about java.
when the System.exit(0); gets executed, the system will break the execution flow and come out the system. this is what is my understanding as of now but I have came across some thing like the below :
Example 1 :
class FinallySystemExit
{
public static void main(String args[])
{
try
{
int a=2/0;
System.exit(0);
}
catch(Exception e)
{
System.out.println("i am in catch block");
}
finally
{
System.out.println("finally");
}
}
}
my understanding about the above code is it will not print anything and exit from the system but the output is :
i am in catch block
finally
Example 2
class FinallySystemExit
{
public static void main(String args[])
{
try
{
int a=2/1;
System.exit(0);
}
catch(Exception e)
{
System.out.println("i am in catch block");
}
finally
{
System.out.println("finally");
}
}
}
when i execute the above code it prints nothing
The difference between two programs are :
First Program :
int a=2/0;
and the
Second Program :
int a=2/1;
I am totally confused and my basic understanding is broken here.
Could some one explain the reason please.
Thanks
In Example 1 :
You perform int a=2/0;
This will throw java.lang.ArithmeticException as you are dividing a number by zero.
As your code is surrounded by try - catch the exception is caught and it printed the statement in catch block and went to finally block
In Example 2:
You perform int a=2/1;
So there is no problem at all.
After executing the above line, your program executed System.exit(0);. So No chance of executing the finally block. That is the reason you don't get any output in this case.
In the first snippet, there is Divide-by-zero error and so the System.exit() is not even called. In the second snippet System.exit() is called and so the JVM exited

Confused with try-catch-finally issue? [duplicate]

This question already has answers here:
Confusing output from infinite recursion within try-catch
(7 answers)
Closed 9 years ago.
I tried to figure out execution order of try-catch-finally in java. I thought execution order should be
try
catch (if error occurred/ exception caught)
finally (whether exception caught or not)
But I am confused with the result of the following
public class TryCatchFinally {
static int i = 0;
public static void main(String[] args) {
try {
System.out.println(i++);
main(args);
} catch (StackOverflowError e) {
System.out.println("Catch");
} finally {
System.out.println("Finally");
}
}
}
Out put(part of an out put)
9127
9128
9129
9130
CatcFCatch // what is the wrong here???
Finally
Finally // there are more Finally printed here.
My question is what is really happening here?
Let me add more why it is not printing "Catch"???
I am getting this out put when run this in IntelliJ IDEA. But when I run in terminal I am getting out put as follows.
9151
9152
9153
9154CatchFinallyCatch
Finally
Finally
Finally
Finally
Chances are that you get a stackoverflow error somewhere inside the println call (possibly because some flushing is going on or something similar), leaving the println method in a inconsistent state (having printed part of what it was supposed to).
That can easily happen when you're already handling a StackOverflowError, because at that point you're already dangerously close to an overflowing stack (since you just recovered from one at a point very close to the problem).
My interpretation looks something like this:
main calls itself recursively a lot ...
you call main for the 9130th time recursively
it prints that number
it calls itself for the 9131st time
it tries to print that number, but throws a StackOverflowError, since the stack is full
you enter the catch and try to print "Catch"
during that println call another StackOverflowError happens
the finally block is executed, because the catch block completed (abruptly)
it tries to print "Finally"
during that println call yet another StackOverflowError happens
that StackOverflowError is caught in the 9130th invocation of main
it prints "Catch" (sucessfully, because the stack is now 1 element shorter!)
the finally-block is executed and prints Finally successfully, because the stack is now 1 element shorter.
more finally blocks execute.
That is because of recursive calls to main. So as you are calling main in main, you are entering multiple times the try catch block, and you are returning from it the same amount of times as you ented it after first StackOverflow occurence. This is the reason on multiple finnalies.
EDIT:
As I saw some downvotes, without any reasonable explanation, if someone thinks I'm wrong, just print the damn i counter with decrementaion in finally block.
public static void main(String[] args) {
try {
System.out.println(i++);
main(args);
} catch (StackOverflowError e) {
System.out.println("Catch");
} finally {
System.out.println("Finally: "+ (i--));
}
}
Are you using an IDE (eclipse or similar), if yes then it could be due to that.
Here is the result of my attempt -
// Code
public static void main(String[] args) throws IOException {
File file = new File("resources/ouput.txt");
file.createNewFile();
PrintStream printStream = new PrintStream(file);
System.setOut(printStream);
overflowTester(0);
}
private static void overflowTester(int index) {
try {
System.out.println(index++);
overflowTester(index);
} catch (StackOverflowError e) {
System.out.println("Catch");
} finally {
System.out.println("Finally");
}
}
// Output
0
1
2
3
4
5
6
7
8
9
10
...
...
...
9666
Catch
Finally
...
...
Finally
Note: '9666' was printed on the 9667th line and the last Finally was on the 19336th line.
In my case, running the following program :
private static int index = 0;
public static void main(String[] args) throws IOException {
try {
System.out.println(index++);
main(args);
} catch (StackOverflowError e) {
System.out.println("Catch");
} finally {
System.out.println("Finally");
}
}
from the command-prompt, yielded similar result :
0
1
2
3
4
5
...
...
9667
Catch
Finally
...
...
Finally
with '9667' being printed on the 9668th line and the last 'Finally' being printed on the 19338th line.

Flow Control with exception

When I run the following code, there are two result.
package scjp;
public class ExceptionTest {
public static void main(String[] args) {
ExceptionTest test = new ExceptionTest();
test.method1();
}
public void method1() {
try {
System.out.println("Try Block");
if (!true) {
return;
} else {
throw new RuntimeException();
}
}finally {
System.out.println("Finally Block");
}
}
}
One result is
Try Block
Exception in thread "main" java.lang.RuntimeException
at scjp.ExceptionTest.method1(ExceptionTest.java:17)
at scjp.ExceptionTest.main(ExceptionTest.java:7)
Finally Block
and the other,
Try Block
Finally Block
Exception in thread "main" java.lang.RuntimeException
at scjp.ExceptionTest.method1(ExceptionTest.java:17)
at scjp.ExceptionTest.main(ExceptionTest.java:7)
Each time I am running the above code, the answer is changing. In my understanding, it should always be same result. Can you help me something???
The system error output stream (the stack trace above, likely in red in your console) is different than the system output stream (your System.out.println() statements). Hence error messages can be out of sync with normal console output since both streams write to the console, but independently of each other. The differences are as follows:
System.out.println("Some text");
prints to the out stream
System.err.println("Error occurred!");
prints to the error stream
The two can get intermixed when outputting to the same console.
The exception stacktrace is not printed on the same outputstrean (it is printed on System.err) and System.err and System.out are not synchronized.
To always have the same output you could print your messages on System.err rather than on System.out.

Categories

Resources