Behavior of a Java process in case of OutOfMemoryError - java

What would be the behavior of a Java program on getting OutOfMemoryError. Is there any defined behavior? Will the process crash or would it go into wait/sleep state?
Update: if I am not handling it in my code?

And OutOfMemoryError is handled like any other exception:
If it is caught, then nothing more happens.
If it is not caught, then either the threads or the threads groups uncaught exception handler handles it. This pretty much always leads to the thread being stopped.
However there are two factors that are not really there in other exceptions:
OutOfMemoryError is an Error and not an Exception. This means that it's very unlikely to be caught anywhere: You should not try to catch an Error generally (with very few exceptions) and it's not usually done, so the chances of it being handled are rather low.
When an OutOfMemoryError happens and no object become eligible for GC because of that, then you'll still have little memory left and chances are that you'll run into the exact same problem again later on.
And if the thread this happens to is the only non-daemon thread (often, but not necessarily, that's the main thread, that executes the main method), then that thread getting killed results in the whole JVM shutting down (which is often perceived as "a crash").
So the tl;dr is: It will probably kill the thread, and if the memory-issue is not solved, then this can happen to more and more threads.

You can't determine the state of program when OutOfMemoryError occurs. If you are not catching Throwable then your program will terminate with the stacktrace. Even if you are catching Throwable, you should call System.exit since there is no point in recovering from it. "Error" is generally thrown by JVM, as oppose to Exception, which is application/programmer specific.

OutOfMemoryError should be considered unrecoverable and the behavior of the JVM after such an error has been raised is undefined, so there is no point in expending effort to handle it. Any operations done after this exception is thrown by the JVM will have undefined behavior. They may execute, but more likely they will just cause another error to be thrown.

Related

JavaFX: Exception on thread is not logged to System output

In my JavaFX 8 app, I have a thread that runs a loop and occasionally updates the UI. Somewhere in this thread, there's an exception causing me grief. Finding it wouldn't be a problem, except exceptions on worker threads don't seem to be logged to System output the same as those on the main program thread.
What I mean is, when I run the program, if something breaks in main(), IntelliJ prints the exception message and a stack trace to the Run view (standard out, AFAIC). On the other hand, if something breaks in my thread, I don't get the same verbose output. In fact, most of the time, I don't get anything at all - just a mysteriously non-functioning program.
Is there another step I need to take to capture errors in worker threads? Is my environment misconfigured? This makes debugging next to impossible - any help appreciated!
Between Samuel's comment and some searching, I've got my answer; Runnables tend to consume their errors, so they're never thrown up to the main thread. This means that with no error handling, they simply disappear and the thread is broken.
The solution in my case is to add try/catch blocks in my task. This is dumping errors the way I expect now.
(I guess your answer/comment means I should turn my comment into an answer.)
Depending on your threading model exceptions are not propagated to the main thread, they just kill the thread they are thrown from. You might benefit from adding a try/catch to your "run" method when starting the thread.

Thread vanishes without a trace

I'm trying to debug an issue. We have few Threads that work on data from a BoundedLinkedQueue. After processing one record, the current thread executes Thread.currentThread().yield().
Now, once a while it is observed that one of the thread just vanishes ! I have traced the logs to find that such a "vanishing" thread works till the yield statement. After that no traces of that thread are found - nor any errors or exceptions are thrown near the last log seen for the thread.
Can anyone give any pointers for debugging directions ? Is the usage of the yield correct ? Is the yield a reliable statement ? This is because I found out this article suggesting to avoid the yield statement ? Has anyone seen such a condition before ?
Edit: On some research, it seems that try/catch may miss some exceptions and those would be just put into System.err which may not be noticeable in a multi-threaded environment. Thanks to #JVerstry for the pointer, I have set uncaughtexceptionhandler for the Thread. The build and run process takes long. Will update more once I have something concrete.
Here are few links that talk about UncaughtExceptionHandler:
Thread.UncaughtExceptionHandler
Catching Uncaught Exceptions in JDK 1.5
Java theory and practice: Hey, where'd my thread go ?
Know the JVM Series 1 - The Uncaught Exception Handler
As pointed out in the article you linked, yield doesn't define whether or not the current quantum is interrupted. If you yield right before thread exit, the scheduler just might complete the quantum for the thread causing the thread to exit immediately.
Yield does not make threads vanish. It is possible that your thread throws an exception and that is not caught. Did you implement an uncaught exception handler? If not, then I recommend you do so. It would explain your problem (unless the thread ends up naturally and your code does not do what you think it should do).
What occurs after the yield? Will the thread exit or will it attempt to process another piece of data from the queue?
You should verify that the what is being called after the yield is actually being called with logging.
How do you know the thread has exited? Have you verified by using by looking at a stack trace (Use Jstack)?
Lastly why are you using yield at all? I assume your BoundedLinkedQueue allows threads to retrieve data in a thread-safe manner, or blocks if the queue is empty. Why not just let the JVM manange thread scheduling?
We were able to get a thread dump when this re-occurred and seems that the thread was just blocking on a JDBC call forever - a bug in the jdbc jar. We just replaced the jar with the latest version and seems to have solved it. Thanks all for the valuable inputs - made me learn a lot of new things. Also, now put a query time out to prevent blocking forever.

Does throwing an Exception have to cause the program to terminate

Does throwing an Exception have to cause the program to terminate?
I think its no, I just want to make sure
It depends on the thread where the exception is thrown, and on the other threads running on the same time in the application.
An uncaught exception terminates the thread where it was thrown. If the rest of the threads are only daemon threads, then yes, the application will be terminated.
According to Thread.setDaemon(boolean) documentation:
The Java Virtual Machine exits when the only threads running are all daemon threads.
No, it does not have to cause it to terminate. You could catch the exception and do something useful with it, like show a message to the user that an error occurred and why.
In Java and .NET, if you don't handle an exception, it will most like cause your program to terminate.
Simply throwing an exception will not terminate the program, as such. It is what happens after it was thrown that determines what will occur.
Failing to catch an exception will likely cause the program to terminate, but the act of throwing one will not. At the very least, any application should have some kind of last line of defense for catching all otherwise unhandled exceptions and handling them (even if handling them means, for some at least, throwing them outside of the application and terminating because something external to the application expects this).
Only "Unhandled Exceptions" will cause your program to crash. To handle exceptions you use the following form
try {
// May Throw ApocalypseException
functionThatMightBlowUpTheWorld();
}
catch (ApocalypseException e){
System.err.println("We accidentally almost blew up the world because: ");
System.err.println(e.message);
}

Java Exception handling mechanism

In Java,If I didn't catch the thrown Exception then the Thread execution stops there else if I catch the same then the Thread execution continues after the catch block.Why Java Exception handling designed in this way.
Thx
The purpose of an exception is to let the program understand that Something Weird Has Happened, and so doing what would ordinarily be next in the program is very likely to be wrong. A function you called couldn't give you a real answer, and you were relying on that answer, so it had to stop you.
There are two ways this can end: you handle the exception (via a catch block), or the entire program stops.
If your program doesn't know what to do when these things happen, it's best to do nothing. Let the Exception crash the thread, and then you can check the crash log later, and find out exactly what crashed the program and why. If your program can't handle an error, the Exception's "crash the thread" behavior lets you see what error was unhandled, so you can change the program to make it able to handle this kind of situation in the future, or prevent the situation from occuring.
Some errors might be pretty normal, though, and shouldn't stop the entire program- you need to have a way to recover from them. That's what a catch block is for: a chance to say "Hello Java, I know just what to do about this problem", and then do it. A Catch block lets you clean up the program and move on, if you can. Java assumes your Catch block deals with the problem and makes it go away. If there's a new problem, or for that matter the same one, you need to throw the caught exception again, or maybe a new one, so something else can try to fix the problem- even if that something else is you, as a programmer.
If exceptions always crashed the program, there would be no way to handle errors that are expected and can be dealt with. But if absolutely nothing is ready to handle the error, the program can't keep running, because now something's gone weird and it doesn't know what to do because you didn't program it to do anything.
In Java,If I didn't catch the thrown Exception then the Thread execution stops there else if I catch the same then the Thread execution continues after the catch block.
There is a third case. If the thread has an Thread.UncaughtExceptionHandler (registered by calling thread.setUncaughtExceptionHandler(handler)), then it will be notified in the event of an uncaught exception on the thread stack ... before the thread exits. (In fact, the behaviour is a bit more complicated than this; see the javadocs.)
Why Java Exception handling designed in this way.
Because the alternative is far worse ... in most cases.
Assuming that the thread has caused the run() method to terminate ('cos you didn't catch the exception), then the only thing you could do "not stop" would be have the thread infrastructure call run() again.
But the uncaught exception typically means something BAD has happened. Typical run() methods are not designed so them multiple times will do something sensible. And if the run() method just failed for some unknown reason (as far as the run() method is concerned), it is even less likely that calling it again will work.
Besides, in the few cases where it is sensible for your run() method to catch and resume from every exception, you can always code it to do that. And if you don't want to the thread to resume, you can implement an "uncaught exception handler" to do notify something else and (maybe) start higher level recovery.
The only thing that is maybe slightly questionable about the current design is that Thread termination due to an uncaught exception is often silent. But the cure for that is to implement a default uncaught exception handler that makes some noise ....

Java try finally variations

This question nags me for a while but I did not found complete answer to it yet (e.g. this one is for C# Initializing disposable resources outside or inside try/finally).
Consider two following Java code fragments:
Closeable in = new FileInputStream("data.txt");
try {
doSomething(in);
} finally {
in.close();
}
and second variation
Closeable in = null;
try {
in = new FileInputStream("data.txt");
doSomething(in);
} finally {
if (null != in) in.close();
}
The part that worries me is that the thread might be somewhat interrupted between the moment resource is acquired (e.g. file is opened) but resulting value is not assigned to respective local variable. Is there any other scenarios the thread might be interrupted in the point above other than:
InterruptedException (e.g. via Thread#interrupt()) or OutOfMemoryError exception is thrown
JVM exits (e.g. via kill, System.exit())
Hardware fail (or bug in JVM for complete list :)
I have read that second approach is somewhat more "idiomatic" but IMO in the scenario above there's no difference and in all other scenarios they are equal.
So the question:
What are the differences between the two? Which should I prefer if I do concerned about freeing resources (especially in heavily multi-threading applications)? Why?
I would appreciate if anyone points me to parts of Java/JVM specs that support the answers.
I don't think there is any reason to be concerned:
1) InterruptedException (e.g. via Thread#interrupt())
Calling Thread.interrupt() does not cause InterruptedException to be thrown spontaneously. The exception is only thrown within specific (and well documented) blocking methods; i.e. blocking I/O and synchronization methods. This exception cannot be thrown after returning from the stream constructor and before entering the try block.
or OutOfMemoryError exception is thrown
If an OutOfMemoryError is thrown, you cannot guarantee full recovery of the underlying file descriptor, no matter where you put the stream constructor. You should never attempt to recover from an OOM, so the question of whether the stream is closed is moot. Besides, this exception is only thrown on a thread that is actually attempting to allocate memory, and that is not happening at this point.
2) JVM exits (e.g. via kill, System.exit())
If the application is being forcibly terminated by an external kill or a System.exit() call, it does not matter if streams are closed properly. Besides, in both cases there is no guarantee that finally clauses will be executed.
3) Hardware fail (or bug in JVM for complete list :)
All bets are off. You have no way of knowing if anything will execute, let alone the finally blocks.
There is one more situation where a thread might receive an spontaneous exception at that point, with some (naive) expectation that it might recover. That is when some misguided programmer decides to call the deprecated Thread.stop() method. You might think that putting the stream constructor call inside the try block would help. But actually it won't, because the ThreadDeath exception could be raised inside the stream constructor between opening the underlying file and completing construction of the stream object. So the FD could leak anyway.
This is just one reason why Thread.stop() is deprecated. Don't use it.
a) Note that interrupting the thread with interrupt() will not take effect immediately, and may not have any effect at all, if the thread being interrupted does not cooperate. There is no way the thread will exit due to interrupt() during the execution of :
Closeable in = new FileInputStream("data.txt");
The only thing that will happen is that its interrupted flag of the thread will be turned on.
b) regarding OutOfMemoryError - I don't see how it can occur right after the construction of the input stream. It may occur in another thread, but this will have no immediate effect on this thread. The problem with OutOfMemoryError, is that your finally block may also fail, because there is not enough memory to complete it...
c) The only way I know that a thread can be interrupted aggressively is using the deprecated methods Thread.stop() and Thread.stop(Throwable).
See a similar discussion here:
Is this a safe way to release resources in Java?
My view is that is when you are working with a managed runtime, such as Java or .NET you really should not (and it's good!) concern yourself with things like your particular question. Only because you are completely disconnected from the underlying operating system and its native APIs. All you have to know is that you call Closable.close() in your finally block and your resource will always be freed.

Categories