Understanding the Java stack - java

There is this code:
public class Main {
public static void main(final String[] args) throws Exception {
System.out.print("1");
doAnything();
System.out.println("2");
}
private static void doAnything() {
try {
doAnything();
} catch (final Error e) {
System.out.print("y");
}
}
}
And there is the output:
1yyyyyyyy2
Why does it print "y" eight times and no more. How can Java call println() when StackOverflowError encountered?

Here you are catching Error and not Exception in which case your program would have crashed.
If you try this code (modified to add a static counter)
public class StackError {
static int i = 1;
public static void main(final String[] args) throws Exception {
System.out.print("1");
doAnything();
System.out.println("2");
}
private static void doAnything() {
try {
i++;
// System.out.println(i);
doAnything();
} catch (Error e) {
System.out.print("y"+i+"-");
}
}
}
Output
1y6869-2
So, it has got stackerror 6869 times(changes for different runs) and the last value is printed. If you just print the y as you did earlier then it might the case that the output is getting bufferred and not getting flushed as it is not a println.
Update
The System.out.println internally calls the PrintStream which is buffered. You don't loose any data from the buffer, it gets all written to the output( terminal in your case) after it fills up, or when you explicitly call flush on it.
Coming back to this scenario, it depends on the internal dynamics of how much the stack is filled up and how many print statements were able to get executed from the catch in doAnything() and those number of characters were written to the buffer. In the main back it finnally get's printed with the number 2.
javadoc reference to buffered streams

My bet is that by invoking print in the catch block you force another StackOverflowError that is caught by the outer block. Some of these calls will not have enough stack for actually writing the output stream.
The JLS says that:
Note that StackOverflowError, may be thrown synchronously by method
invocation as well as asynchronously due to native method execution
or Java virtual machine resource limitations.
The Java SE platform permits a small but bounded amount of execution
to occur before an asynchronous exception is thrown.
The delay noted above is permitted to allow optimized code to detect
and throw these exceptions at points where it is practical to handle
them while obeying the semantics of the Java programming language. A
simple implementation might poll for asynchronous exceptions at the
point of each control transfer instruction. Since a program has a
finite size, this provides a bound on the total delay in detecting an
asynchronous exception.

The first time the StackOverFlowError occurs, the call to the last doAnything() is cancelled and the control is returned to the catch block from the last doAnything().
However, because the stack is still practically full, the simple fact of calling System.out.print("y") will causes another StackOverflowError because of the need of pushing some value on the stack and then make a call to the function print().
Therefore, another StackOverflowError occurs again and the return is now returned on the catch{} block of the previous doAnything(); where another StackOverflowError will happens because the need of stack space required to do a single call to System.out.println("y") is greater than the amount of space liberated from returning a call from doAnything().
Only when there will be enough space on the stack to execute a call to System.out.print("y") that this process will stop and a catch block will successfully complete. We can see that by running the following piece of code:
public class Principal3b {
static int a = 0;
static int i = 0;
static int j = 0;
public static void main(String[] args) {
System.out.println("X");
doAnything();
System.out.println("Y");
System.out.println(i);
System.out.println(j);
}
private static void doAnything() {
a++;
int b = a;
try {
doAnything();
} catch (final Error e) {
i++;
System.out.println(a);
System.out.println(b);
j++;
}
}
}
Notice that a println(a) is used instead of a print(a); therefore a new line should be printed after each value of a if everything runs OK.
However, when I run it, I get the following result:
X
62066206620662066206620662066206
6190
Y
17
1
This means that there have been 17 attempts ro run the catch block. Of these catch block executions, 9 are unable to print anything before generating themselves a StackOverflowError; 7 are able to print the value of 6190 but are unable to print a newline after it before themselves rising an error again and finally, there is one that is able to both print the value of 6190 and the newline after it; therefore finally permitting its catch block to complete without any new StackOverflowError and return gracefully up the calls stack.
As we are dealing with StackOverflowError, these numbers are only an example and will vary greatly not only between machines but also between executions and the simple fact of adding or removing any kind of instructions should also change these values. However, the pattern seen here should remains the same.

One thing is clear that System.out.print("y"); in catch creates this puzzle. If we change the code as
static int n;
public static void main(final String[] args) throws Exception {
System.out.println("1");
doAnything();
System.out.println(n);
}
private static void doAnything() {
try {
doAnything();
} catch (Error e) {
n++;
}
}
it prints
1
1

Well the no. of times the stack overflow error is hit is undefined. However, the JVM allows you to recover from StackOverflowError error and continue execution of the system normally.
It is proved by the following code:
public class Really {
public static void main(final String[] args) throws Exception {
System.out.print("1");
doAnything();
System.out.println("2");
}
private static void doAnything() {
try {
throw new StackOverflowError();
//doAnything();
}
catch(final Error e){
System.out.print("y");
}
}
}
Note however, as #Javier said, the StackOverflowError is thrown by the JVM synchronously or asynchronously(which means it can be thrown by another thread, possibly a native thread) which is why it is not possible to get the stack trace of the error. The no. of times the thread(s) hit the catch() block is undefined.

In addition, Objects of type Error are not Exceptions objects they represent exceptional conditions.
Errors represent unusual situations that are not caused by program errors,
usually does not normally happen during program execution, such as JVM running out of memory.
Although they share a common superclass Throwable, meaning both can be thrown, it can
be placed in a catch but generally not supposed to be caught, as they represent
rare, difficult-to-handle exceptional conditions.

Stack overflow.
You are only printing on exception,in the meantime the program recurses into overflow.
At which point this occurs depends on individual systems, memory, etc.
What is the purpose of the program?

Related

Is it okay to call the the method a try catch statement is in with the finally block

I made a switch case statement menu with one of the options being System.exit(0);. This is all surrounded by a try, finally that calls the method all of this is in. Would you guys not recommend this style of loop or am I all good?
public void Run() {
Scanner myObj = new Scanner(System.in);
int menuInput;
try {
System.out.println(" 1) call something\n"
+"2) quit");
menuInput = myObj.nextInt();
myObj.nextLine();
switch(menuInput) {
case 1:
something();
break;
case 2:
System.exit(0);
break;
}
}catch (Exeption e ){
System.out.println("Something went wrong.");
}finally{
Run();
}
}
No.
What you have here is an infinite recursion. Eventually you'd overflow the stack.
Use an actual loop instead:
while (true) {
try {
// ...
} catch (Exception e) {
// ...
}
}
And you almost never want to call System.exit. Just break the loop instead.
Is this legal code? Yes.
Is what you have there recommended? No.
If the method throws an exception it's likely recalling it will throw again. See the quote below.
Calling it again in a tight loop without attempting remedy, at least waiting a recovery and counting failures (3 strikes out?) will just end up in a tight loop of failure and stack overflow here.
So:
Can you identify errors that retrying may work and only retry on those?
You should almost certainly include some kind of 'back-off' wait before retry.
Always (always!) include a maximum retry number after which you accept failure.
In my experience the only kind of failure that may work on retry is 'service unavailable' meaning an intermittent outage.
It may not be relevant, but things like (say) invalid credentials aren't going to fix themselves and ideally you don't resubmit those. That's particularly because you end up locking the account and being in an even worse state and possibly causing issues for others using the valid credential...
The other scenario is (say) file not found and you're using the non-existence of a file as a way of polling for something.
That's a poor design pattern and is a misuse of exception handling.
You should strongly prefer to use some kind for existence check in those cases and not let routine activity get confused with exception handling of issues.
Also if you do retry log each attempt (it may be useful later to see whether things are running smoothly or getting delayed in retry scenarios even if the go through eventually). But always differentiate a 'Warning' when retrying and 'Error' when 'throwing in the towel' and failing.
public class Runner {
private static int MAX_RETRIES=3;
private static int BACK_OFF_MILLIS=30000;
public void Run() throws Exception,InterruptedException {
final int TRIES=3;//In reality may be configured.
int trycount=1;
for(;;){
try{
tryRun();
return;
}catch(Exception e){
String message=e.getMessage();
if(trycount>=MAX_RETRIES){
System.out.println("*FAILED*: "+e.getMessage());
throw e;
}
boolean retriable=true;
//Any tests for non-retriable exceptions here...
if(!retriable){
System.out.println("*FAILED*: non-retriable exception - "+e.getMessage());
throw e;
}
++trycount;
System.out.println("Warning: "+e.getMessage()+" retrying "+ trycount+" of "+TRIES);
try {
Thread.sleep(trycount*BACK_OFF_MILLIS);//Some kind of back-off...
}catch(InterruptedException ie){
System.out.println("*FAILED*: Interrupted. Aborting.");
throw ie;
}
continue;
}
}
}
public void tryRun() throws Exception{
//Real workload goes here!
}
}
NB: The back-off strategy here is very simplistic. When it comes to outages then it's usually recommended to implement a random element and an increasing back-off like 1 minute, 10 minutes, 25 minutes. But that's a topic in itself.
I'm not sure who really said but this popular quote seems relevant.
The definition of insanity is doing the same thing over and over again
and expecting different results

Why java recursively calling function can run forever even though StackOverflowError? [duplicate]

This question already has answers here:
Why is it possible to recover from a StackOverflowError?
(5 answers)
Closed 12 months ago.
I met the following problem in a Java exam, why following recursively calling a function can run forever even though StackOverflowError?
public class Solution {
static int i = 0;
public static void f(){
System.out.println(i++);
try {
f();
} catch (StackOverflowError e) {
System.out.println(e);
f();
}
}
public static void main(String[] args) {
f();
}
}
I cannot understand why JVM can still run when I've exhausted all call stack memory? Is there any reference, like JVM specification or JVM source code, can explain above phenomenon?
I'm neither java nor jvm expert, but I think adding a extra recursive depth output can show exactly what is going on with the call stack.
public class Solution {
static int i = 0;
public static void f(int depth) {
System.out.println(i++);
System.out.println(String.format("depth=%d", ++depth));
try {
f(depth);
} catch (StackOverflowError e) {
System.out.println(e);
f(depth);
}
}
public static void main(String[] args) {
f(1);
}
}
In my test, typical output is
...more
java.lang.StackOverflowError
161735
depth=3745
161736
depth=3746
161737
java.lang.StackOverflowError
161738
java.lang.StackOverflowError
161739
java.lang.StackOverflowError
161740
depth=3744
161741
depth=3745
...more
StackOverflowError is thrown because jvm is considering a size limit(1M by default?) of stack memory has reached, but the exception is caught, so the recursion is not stopped, it still tries to call, jvm throw away the recent 1 or 2 problematic calls, and then try continue, so the depth value goes around the same maximum value again and again.
I think this way the OP can understand why i is increasing without any problem. I've exhaust the call stack memory -- you haven't, you nearly exhaust, but jvm always cleared latest few calls to avoid exhaust.

throwing an unknown exception in java web application [duplicate]

I am going through a socket program. In it, printStackTrace is called on the IOException object in the catch block.
What does printStackTrace() actually do?
catch(IOException ioe)
{
ioe.printStackTrace();
}
I am unaware of its purpose. What is it used for?
It's a method on Exception instances that prints the stack trace of the instance to System.err.
It's a very simple, but very useful tool for diagnosing an exceptions. It tells you what happened and where in the code this happened.
Here's an example of how it might be used in practice:
try {
// ...
} catch (SomeException e) {
e.printStackTrace();
}
Note that in "serious production code" you usually don't want to do this, for various reasons (such as System.out being less useful and not thread safe). In those cases you usually use some log framework that provides the same (or very similar) output using a command like log.error("Error during frobnication", e);.
I was kind of curious about this too, so I just put together a little sample code where you can see what it is doing:
try {
throw new NullPointerException();
}
catch (NullPointerException e) {
System.out.println(e);
}
try {
throw new IOException();
}
catch (IOException e) {
e.printStackTrace();
}
System.exit(0);
Calling println(e):
java.lang.NullPointerException
Calling e.printStackTrace():
java.io.IOException
at package.Test.main(Test.java:74)
It helps to trace the exception. For example you are writing some methods in your program and one of your methods causes bug. Then printstack will help you to identify which method causes the bug. Stack will help like this:
First your main method will be called and inserted to stack, then the second method will be called and inserted to the stack in LIFO order and if any error occurs somewhere inside any method then this stack will help to identify that method.
printStackTrace() helps the programmer to understand where the actual problem occurred. printStacktrace() is a method of the class Throwable of java.lang package. It prints several lines in the output console.
The first line consists of several strings. It contains the name of the Throwable sub-class & the package information.
From second line onwards, it describes the error position/line number beginning with at.
The last line always describes the destination affected by the error/exception. The second last line informs us about the next line in the stack where the control goes after getting transfer from the line number described in the last line. The errors/exceptions represents the output in the form a stack, which were fed into the stack by fillInStackTrace() method of Throwable class, which itself fills in the program control transfer details into the execution stack. The lines starting with at, are nothing but the values of the execution stack.
In this way the programmer can understand where in code the actual problem is.
Along with the printStackTrace() method, it's a good idea to use e.getmessage().
printStackTrace() prints the locations where the exception occurred in the source code, thus allowing the author who wrote the program to see what went wrong. But since it shows problems in the source code, the user(s) who may or may not have any coding experience may not be able to understand what went wrong, so if the program allows the user to send error messages to the authors, the users may not be able to give good data on what went wrong.
You should consider the Logger.getLogger() method, it offers a better exception handling (logging) facility, and besides printStackTrace() without arguments is considered to be obsolete and should ONLY be used for debugging purposes, not for user display.
The printStackTrace() helps the programmer understand where the actual problem occurred. The printStackTrace() method is a member of the class Throwable in the java.lang package.
printStackTrace is a method of the Throwable class. This method displays error message in the console; where we are getting the exception in the source code. These methods can be used with catch block and they describe:
Name of the exception.
Description of the exception.
Location of the exception in the source code.
The three methods which describe the exception on the console (in which printStackTrace is one of them) are:
printStackTrace()
toString()
getMessage()
Example:
public class BabluGope {
public static void main(String[] args) {
try {
System.out.println(10/0);
} catch (ArithmeticException e) {
e.printStackTrace();
// System.err.println(e.toString());
//System.err.println(e.getMessage());
}
}
}
printStackTrace() helps the programmer to understand where the actual problem occurred. It helps to trace the exception.
it is printStackTrace() method of Throwable class inherited by every exception class. This method prints the same message of e object and also the line number where the exception occurred.
The following is an another example of print stack of the Exception in Java.
public class Demo {
public static void main(String[] args) {
try {
ExceptionFunc();
} catch(Throwable e) {
e.printStackTrace();
}
}
public static void ExceptionFunc() throws Throwable {
Throwable t = new Throwable("This is new Exception in Java...");
StackTraceElement[] trace = new StackTraceElement[] {
new StackTraceElement("ClassName","methodName","fileName",5)
};
t.setStackTrace(trace);
throw t;
}
}
java.lang.Throwable: This is new Exception in Java...
at ClassName.methodName(fileName:5)
What is the use of e.printStackTrace() method in Java?
Well, the purpose of using this method e.printStackTrace(); is to see what exactly wrong is.
For example, we want to handle an exception. Let's have a look at the following Example.
public class Main{
public static void main(String[] args) {
int a = 12;
int b = 2;
try {
int result = a / (b - 2);
System.out.println(result);
}
catch (Exception e)
{
System.out.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
}
I've used method e.printStackTrace(); in order to show exactly what is wrong.
In the output, we can see the following result.
Error: / by zero
java.lang.ArithmeticException: / by zero
at Main.main(Main.java:10)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Can System.exit() return without terminating the JVM?

In practice of course it is very unlikely to happen, but:
Is there any reason for this method call not to terminate the JVM?
Is it possible for example, that an OutOfMemoryError is thrown immediately after (or while) calling System.exit(0) or that a StackOverflowError occurs when calling this method, because the stack is just overflowing in that moment?
Is there any reason for this method call not to terminate the JVM?
Yes.
From the docs:
Throws:
SecurityException - if a security manager exists and its checkExit method doesn't allow exit with the specified status.
I'm unable to produce a stack overflow on System.exit()
public static void main(String[] args)
{
try
{
main(args); // recursion
}
catch (StackOverflowError e1)
{
System.out.println("OK.");
}
try
{
System.exit(0);
}
catch (StackOverflowError e2)
{
System.out.println("HA!");
}
}
After e1 occurs, println() and exit() still work, as if there are still some space on stack.

Exception with try-catch and loop in Java

In Java, what is the difference (in term of performance) between:
for (int i = 0; i < count; i++) {
try {
// code that throws Exception
} catch (Exception e) {
e.printStackTrace();
}
}
and
try {
for (int i = 0; i < count; i++) {
// code that throws Exception
}
} catch (Exception e) {
e.printStackTrace();
}
In your first version the loop continues if it hits an exception, in the second version the loop continues after the catch block. That is the most important difference of those code snippets.
You can use both, but it all depends on what you want it to do. If you want to continue the execution after the loop finishes once then you do it the first way. If you want to catch an exception then stop executing the loop then you do the second. Performance wise it all depends on what you want to do with it.
The main difference is that in the first snippet of code, even if there is an exception thrown from the try block and it is caught execution of the for loop continues. In the second snippet if an exception is thrown then the for loop is exited. This is because the whole loop is within the try block.
No I'm quite sure there's absolutely no difference from a point of performance here (ignoring the obvious fact about the loop). In both cases you create exactly one entry in the exception table - only the PC values (ie in which range the exception is valid) will be a bit different.
ie if you assume the following is the exception table the only thing that'll change are the x, y and z values..
Exception table:
from to target type
x y z <Class java.lang.Exception>
Since you asked about performance in the two versions of code, I am reminded of "Practical Java" (Addison-Wesley 2000) which recommends in Praxis 23: Place try/catch blocks outside of loops. The reason involves running the code on a JVM with the JIT compiler turned off. In that case, the lack of run-time JIT optimizations results in extra branches in the opcode, leading to reduced performance. You can read JIT docs of 2014 here: http://www.oracle.com/technetwork/articles/java/architect-evans-pt1-2266278.html
Besides the difference in your logic with the continuing for. It's no noticeable difference between
try {
lots of stuff which might not throw any exception
something that throws exception
} catch (Exception e) {
}
and
lots of stuff which might not throw any exception
try {
something that throws exception
} catch (Exception e) {
}

Categories