Is it possible to recover java thread by doing the next?
Thread.setDefaultExceptionHandler(new UncaughtExceptionHandler() {
public void unchaughtException(Thread t, Throwable e) {
t.start();
}
});
Yes it is possible to run a Thread in a Thread.UncaughtExceptionHandler.uncaughtException ... provided that the Thread hasn't been started previously.
But it is NOT possible to start the Thread that was pass as the t argument. That will (always) be a Thread that has already been started and has terminated.
You can start a given Thread at most once. If you try to start one a second time you will get an InvalidStateException. Always.
No, you cannot run the thread that threw the exception, as shown in your code. It has already run. That's how it threw the exception. A thread cannot be started more than once.
Related
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.
I'm trying to understand concurrent execution in Java, but given this code :
class Inter extends Thread {
public void run() {
System.out.println("Starting...");
try {
sleep(10000);
} catch (InterruptedException e) {
System.out.println("Interrupted."); }
System.out.println("Finished.");
}
public static void main(String[] args) {
Inter hi = new Inter();
hi.start();
System.out.println("Sending interruption...");
hi.interrupt();
System.out.println("Sent.");
}
}
I don't know why always give me this trace :
Sending interruption...
Sent.
Starting...
Interrupted.
Finished.
No matter how many times I run :
$ java Inter
As fars as I know in Java, when we execute the start() method in a new thread, the execution of this thread starts.
So , since the main thread and the Inter thread are concurrently executed, why can't be this a possible trace, ?
Starting..
Sending interruption..
Sent
Interrupted
Finished
So, since the main thread and the Inter thread are concurrently executed, why can't be this a possible trace?
Yes, it can. If you run your program a thousand times, most probably you will have that output at least once.
It's up to the operating system thread scheduler to arrange the threads execution in order to give that possible output, but we have no control over the scheduler. Hence, the importance of properly designing your code to prevent race conditions.
Some of my users have been reporting IllegalThreadStateExceptions, which lead back to the following code. I was unable to recreate it, and most people are able to execute this part of the code with no issues.
The code is re-executed periodically, so the old thread should be replaced by a new one and started, but that's where the error occurs.
if (head.threadSeal != null)
{
head.threadSeal.interrupt();
}
head.threadSeal = new ThreadFindSeal();
head.threadSeal.start(); // IllegalThreadStateException here
Relevant stack trace:
java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:704)
Am I missing something in the documentation, why would start ever fail on a new thread?
The javadoc of Thread#start() states
Throws: IllegalThreadStateException - if the thread was already
started.
You haven't give much information, but the following could happen.
First thread executes
head.threadSeal = new ThreadFindSeal();
Second thread then executes
head.threadSeal = new ThreadFindSeal();
head.threadSeal.start();
replacing the Thread and starting it.
The first thread then executes
head.threadSeal.start();
which is called on the same Thread object as before, which was already started.
I have a requirement, that I want to start a poller once which will run foreever until the machine is restarted or the process is being killed. Now, I tried to start the poller from a main method using a shell script, but the problem is that as soon as the main method completed its execution, the poller also stoped working, as i am not using any servers to achieve so.
I heard something about daemon threads, but I am wondering how to create a daemon thread, which will run forever, and help my poller to run also.
UPDATE:
public class SomeThread extends Thread {
#Override
public void run() {
UnitPoller unitPoller = new UnitPoller();
unitPoller.doPolling();
}
public static void main(String[] args) {
SomeThread someThread = new SomeThread();
someThread.setDaemon(true);
someThread.start();
}
}
Above is my updated class, now whenever I execute this thread from the main method, it creates a thread but as soon as the execution of main method completes, my poller stops working, as the JVM shuts down.
With this problem, what should i do.
Thanks
You just create a thread and call th.setDaemon(true) before calling th.start().
Edit:
The above answers the question "how to create a daemon thread", but (as the scope of the question has changed), a proper answer would be: don't create a daemon thread if you want your thread to keep the JVM from exiting once the main thread completed.
1) You need someThread.setDaemon(false) instead of 'true'. A daemon thread actualy does NOT stop java from shutting down.
From the javadoc:
void java.lang.Thread.setDaemon(boolean on)
Marks this thread as either a daemon thread or a user thread. The Java Virtual Machine exits when the only threads running are all daemon threads.
This method must be called before the thread is started.
2) I think it's not your main, but your run() method that finishes to soon. Try to put a while (true) loop around your doPolling method.
#Override
public void run() {
UnitPoller unitPoller = new UnitPoller();
while (true)
unitPoller.doPolling();
}
3) It's cleaner to call join() inside the main then to rely on daemon thread behavior.
try {
someThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
4) If you need a clean way to shut down the deamonthread. Consider implementing InterruptedException to exit the polling task. You can also use the shutdown hook.
The term "daemon thread" in Java is a bit misleading, as it really means "that thread is not supposed to keep the JVM alive". This means that the JVM will shut down as soon as the last non-daemon thread terminated (as you already stated in your question).
What you are possibly looking for is the Apache Commons Daemon project, which allows to create nice "system services", started through /etc/init.d/ entries and all. This works on Windows and *nix systems.
When i execute the below code,I am seeing the output as:
Finally
Exception in thread "main" java.lang.NullPointerException
at ClientTestConcepts.main(ClientTestConcepts.java:9)
Who prints the bold faced statements.
public class ClientTestConcepts {
public static void main(String []args){
try{
throw new NullPointerException();
}
finally{
System.out.println("Finally");
}
}
}
The Java runtime.
It catches all exceptions not handled in user code, and prints them on the error output (by default).
Each thread has a default uncaught exception handler that runs when an exception makes it to the top of the stack. The one you are observing is provided by ThreadGroup.uncaughtException:
Called by the Java Virtual Machine when a thread in this thread group stops because of an uncaught exception, and the thread does not have a specific Thread.UncaughtExceptionHandler installed.
The uncaughtException method of ThreadGroup does the following: (...)
... a message containing the thread's name, as returned from the thread's getName method, and a stack backtrace, using the Throwable's printStackTrace method, is printed to the standard error stream.
If you want some other behaviour register an uncaught exception handler for the thread.