Stuck thread after throwing unhandled exception - java

I have an application that runs headless and needs to be able to notify administrators of problems. I built an email notification framework for it to use, and basically if an exception is thrown and caught, depending on the area in code and the criticality of the exception, it may be passed into the alert notification framework which triggers an email to go out to the listed admins with the stack trace and other debug info.
This works, pretty well.
Before deploying, I was putting it through it's paces. One of my tests is to throw an unhandled exception from a random spot in code - simulating a potentially serious runtime problem where exceptions are being thrown that we did not expect.
For example, here is a method I inserted the test unhandled exception:
/**
* Closes connection.
*/
public void closeConnection() {
if (true)
throw new NullPointerException("Test unexpected exception NPE");
LOG.info("Closing SFTP connection");
getSftpChannel().exit();
getSession().disconnect();
LOG.debug("SFTP Connection closed");
}
The code runs, and when it gets to this unhandled exception, the program hardlocks (because exception is thrown and the sftp connection thread is never closed, so it holds the jvm open until the connection timeout).
I had thought it would crash the JVM, or pass it up to it's caller which eventually would bubble up to the alert system.
In this scenario, I had assumed this NPE would throw out of this exception, isn't handled by it's caller or the caller's caller, etc, so it should bubble to the main() and then crash the JVM since even main does not catch Exception or NPE's.
Question: What is going on here and how can I ensure a scenario like this won't hang in production? Do I just had a huge catch-all catch clause to my main() and have it catch all Exception so that every exception gets handled?
EDIT FOR CLARITY: The question is more-or-less -- Why does an unhandled exception that is not explicitly thrown in a method's signature, nor handled by a caller, not crash the JVM?

To answer your question: Why does an unhandled exception that is not explicitly thrown in a method's signature, nor handled by a caller, not crash the JVM?
Assuming this code is running in a Thread, the reason is, that unless you've set an UnhandledExceptionHandler on either the Thread class or the Thread instance, then the 'main' thread group is the default UnhandledExceptionHandler. By default, the thread group handles unhandled exceptions by logging the stack trace to system.out, the thread 'dies' and the JVM does not crash.
You may want to consider implementing an UnhandledExceptionHandler that uses your email framework to notify you of these failures.
As other posters have suggested, the code should clean up resources like Channels and Session in a finally block.

use a finally block to ensure the connection is closed.
public void closeConnection() {
try {
if (true)
throw new NullPointerException("Test unexpected exception NPE");
} finally {
LOG.info("Closing SFTP connection");
getSftpChannel().exit();
getSession().disconnect();
LOG.debug("SFTP Connection closed");
}
}

Related

Does an unhandled runtime exception crash the whole server?

Will an unhandled runtime exception stop the whole server (i.e. Spring Boot application) or just the specific HTTP request ?
It is true that an unhandled runtime exception will instantly shut down normal Java application, right ?
Will an unhandled runtime exception stop the whole server (i.e. Spring Boot application) or just the specific HTTP request ?
Just the current HTTP request ... assuming that the exception is thrown by the request thread. (If it is thrown by a child thread, it won't even terminate the HTTP request.)
It is true that an unhandled runtime exception will instantly shut down normal Java application, right?
Actually, not right.
An uncaught exception causes the thread on which it was thrown to terminate. In a simple Java application where there is only one (non-daemon) "main" thread, and an uncaught exception occurs on that thread, the JVM then exit because the last non-daemon thread has terminated.
But if there are other threads ... the uncaught exception doesn't stop the JVM.
To illustrate, run this program:
public class Test {
public static void main(String[] args) {
new Thread(() -> {
try {
Thread.sleep(10000);
} catch (Exception e) {
System.err.println("Caught " + e);
}
}).start();
throw new RuntimeException("Goodbye cruel world");
}
}
When you run this, you will observe that there is a 10 second delay between the stacktrace printing (from the uncaught exception in main) and the program actually ending. The JVM is waiting for the child thread to terminate.
This could also indirectly answer your main question ... except:
We don't know for sure if the request threads are daemon threads or not.
We don't know for sure that the request threads are not actually catching / handling the exceptions thrown by your request processing code.
Suffice it to say that a framework will typically do something sensible depending one what the thrown exception is. For example, a framework might handle Error exceptions on a worker thread by attempting a shutdown ... on the basis that the error may have put the JVM into a potentially unsafe / non-recoverable state.
Just the thread in question
An unhandled RuntimeException will kill the thread, not the application. Usually each HTTP request is handled by its own thread, so nothing else in the server should be affected. I don’t know how the server handles the dead thread. A wise move would probably be creating a new thread for upcoming requests.
Only when all threads (except so-called demon threads) are terminated, will your Spring Boot application stop. This in turn means that in an application that isn’t threaded — one that has everything running in the main thread — an uncaught exception (RuntimeException or some other type) will bring the whole program down.
In most applications it matters which thread is killed. Your application probably has more threads handling HTTP requests and can spawn new ones as needed. In this case a thread death will hardly be noticed except by the user having sent this HTTP request. Other threads are probably more vital to the functioning of the server, and such a thread being killed, while not stopping the server completely, will stop it from working properly. For a different example, if the event dispatching thread in a desktop application is killed by an exception, the application can no longer accept user input.
Try it out for yourself
It doesn’t take a lot to try it out. The following program spawns a thread that throws an unhandled exception.
public class DemoUnhandledException {
public static void main(String[] args) throws InterruptedException {
new Thread(() -> { throw new RuntimeException("Demo"); }).start();
TimeUnit.MINUTES.sleep(1);
System.out.println("A minute later the main thread is still alive and well");
}
}
Let the program run for a full minute to get the full output, which is:
Exception in thread "Thread-0" java.lang.RuntimeException: Demo
at ovv.so.exception.DemoUnhandledException.lambda$0(DemoUnhandledException.java:8)
at java.base/java.lang.Thread.run(Thread.java:834)
A minute later the main thread is still alive and well
Link
How uncaught exceptions are handled in Java on Javamex
Will an unhandled runtime exception stop the whole server (i.e. Spring Boot application) or just the specific HTTP request ?
There is usually a thread pool in web server to handle all requests(e.g tomcat). Uncaught exceptions that occur in your controller will eventually be caught somewhere, so it will not cause the worker thread in the thread pool to be killed.
Tomcat#AbstractEndpoint#processSocket:
Executor executor = getExecutor();
if (dispatch && executor != null) {
// handle request in thread poll
executor.execute(sc);
}
I did a simple debug. Assuming that an unhandle exception occurred in your controller, then the exception was actually caught by FrameworkServlet#processRequest. After the capture, it will be wrapped into a NestedServletException and continue to be thrown to the upper layer. Eventually, it will be caught and printed in StandardWrapperValve#invoke.

How to avoid from java.nio.channels.ClosedByInterruptException exception during stopping async method

I have some method with render() name which includes very difficult logic and I call it so in my code
Future<File> fileFuture = null;
try {
fileFuture = executor.getThreadPoolExecutor()
.submit(() -> render());
return fileFuture.get(10,TimeUnit.SECONDS);
} catch (TimeoutException e) {
fileFuture.cancel(true);
throw new MyTimeOutException(e);
}
}
render() method opens some I/O resources and when job doesn't finish
till timeout I get such error when timeout happens
java.nio.channels.ClosedByInterruptException
I investigated this problem and found that this happens because
I/O resources stay still open and Thread cannot be terminated
till these resources won't be closed.
But isn't any way for avoiding this exception
I just need to stop my async method when timeout happens.
and I also want add that I use Spring boot if there is any solution with
Spring please tell me
This exception ClosedByInterruptException will be thrown when a thread performing a blocking read or write on an InterruptibleChannel, like a FileChannel, it's interrupted.
When you call fileFuture.cancel(true) the boolean flag indicates that if the task is blocked, the thread may be interrupted. So, as the thread is blocked in a read or write operation it throws a ClosedByInterruptException.
If you want to get rid of the ClosedByInterruptException, then you render() method to tackle with ClosedByInterruptException, to end the process gracefully if it's thrown.

picocli exception behavior changed?

I'm in the process of updating from picocli 3.9.6 to 4.2.0, and I'm running into an issue when replacing old deprecated calls with the new versions.
In my original version, I had a code block like this:
try {
return commandLine.parseWithHandlers(
new RunLast().useOut(ps),
new ExceptionHandler(),
args);
}
catch(Exception e) {
// handle exceptions
}
The ExceptionHandler handles both parameter and execution exceptions -- both are rethrown, but parameter exceptions get the help text added to the exception text. The catch would get hit in cases where, e.g., a command was given bad args. The catch would ensure the error was printed in the UI.
I attempted to update it like this:
try {
commandLine.setOut(pw);
ExceptionHandler handler = new ExceptionHandler();
commandLine.setExecutionExceptionHandler(handler);
commandLine.setParameterExceptionHandler(handler);
commandLine.execute(args);
return commandLine.getExecutionResult();
}
catch(Exception e) {
// handle exceptions
}
With this new version, exceptions are thrown as before, but they are no longer caught by the catch block after being rethrown by the ExceptionHandler. How can I catch these exceptions?
One of the changes in picocli 4.x is the new execution framework. The user manual has a section on migration that may be useful.
By design, the CommandLine::execute method never throws an exception. So there is no need to surround the call to CommandLine::execute with a try/catch block (unless you need to catch an Error or Throwable).
Instead, you can optionally specify custom exception handlers, like you already do in your example. These exception handlers is where you can show an error message to the users. (Perhaps a combination of what was in the previous ExceptionHandler and the logic that previously was in the catch block.)
The ParameterExceptionHandler is invoked when the user provided invalid input. The default handler shows an error message, may suggest alternative spellings for options or subcommands that look like a typo, and finally displays the usage help message. The Handling Errors section of the user manual has an example ShortErrorMessageHandler that may be useful when the usage help message is so long that it obscures the error message.
The ExecutionExceptionHandler is invoked when the business logic throws an exception. The default handler just rethrows the exception, which results in a stack trace being printed. The Business Logic Exceptions section of the user manual shows an alternative.
It sounds like you need a custom ExecutionExceptionHandler that prints a stack trace followed by the usage help message.

Who killed My Java Infinite loop thread?

As the title suggested, I have some code wrapped in a while(true) infinite loop, and all of them are fully caught by try and catch block. This thread is started in the main method, however, after long run, this worker thread is vanished mysteriously when I check using the jstack and causing work accumulated.
Below is my code:
public void run() {
while (true) {
try {
// Consumer consumes from Kafka server
Global.KAFKA_METRIC_DATA_CONSUMER.consume(topic, handler);
} catch (Exception e) {
logger.error("Kafka consumer process was interrupted by exception!");
} finally {
try {
// Prevent restart too often
Thread.sleep(30 * BaseConst.SECOND);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
For my understanding, this structure will keep the thread running so is the consumer. Even if the consume() methods failed, it will restart infinitely. However, as I mentioned above, the whole thread disappear silently without any error log. Could anyone provide some clue please?
Some more information that might be helpful:
I have checked the consume method will never shutdown the consumer
nor close the socket to the server. It will continuously try to
connect server after fail.
I analysed the java heap dump, and I found there is a memory leak
somewhere else in the project, causing memory occupation extremely
high and the gc very often. However, the main method is still
running.
OutOfMemoryError is not an Exception. It's an Error derived from Throwable.
If that was thrown somewhere in your consume(topic, handler), finally would still be called, delaying the inevitable some 30s... but after that the error would be passed upward and your loop would be terminated.
You are catching Exception so there's a chance that a java.lang.Error or a java.lang.Throwable is being thrown (eg OutOfMemoryError)
If you really want to catch everything, you'll need to catch Throwable and not just Exception subclasses.
Your thread is probably killed by an error.
An error is not an exception! But they both extend Throwable
Add another catch block that catches errors.
Throwable should never be caught, because errors require a different handling than exceptions

Getting unreachable statement error even though it reaches during run time in spring hibernate

I am trying to catch exceptions which will occur during run time in spring hibernate below is hibernate code which inserts data into sql table but i want to catch certain exceptions but i am getting below
error:
Unreachable catch block for JDBCConnectionException.
This exception is never thrown from the try statement body
try
{
TokenBo tokenBo = (TokenBo)appContext.getBean("TokenBo");
Token token = new Token();
token.setFirstName(FirstName);
tokenBo.save(token);
}
catch(JDBCConnectionException e1) {}
Runtime Exception & Error are supposed to happen at run time (reporting that something went wrong when the program ran) and ConstraintViolationException is a runtime exception
The error you are getting is because ConstraintViolationException is never thrown from your code.
Why would you even want to catch ConstraintViolationException? This exception states that you failed to fulfill one of the DB constraints, which means you didn't have proper data check in place
To avoid "chat" mode in commens:
The error message is pretty self-explanatory:
This exception is never thrown from the try statement body
Remove the catch block for the ConstraintViolationException. Don't try to handle Exceptions that can not be thrown by your code.
If you remove this, and running your code causes a JDBCConnectionException, you'll need to tackle this problem, not creating another one to hide it.
If you need help to fix that issue, you'll have to provide more code/configuration/stacktrace/...

Categories