Exception handling is not designed to process problems associated with asynchronous events (e.g., disk I/O completions, network message arrivals, mouse clicks and keystrokes), which occur in parallel with, and independent of, the program’s flow of control.
How is exception handling not designed to handle asynchronous events? Why is this the case?
I'll be thankful if you enhanced your answers by quite detailed examples.
I think that is a misleading statement.
Asynchronous work is done through threads in Java (or processes but that is a different matter).
What is true is that if you start a thread and an exception is thrown in that thread, you won't be able to catch it from your main thread.
But nothing prevents you from handling exceptions in that new thread.
Example - the code below prints Exception was raised in the thread but we can still handle it:
public static void main(String[] args) throws Exception {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
throw new RuntimeException("oops");
}
});
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Exception was raised in the thread but we can still handle it");
}
});
t.start();
}
Alternatively, you can add some exception catching logic within the Runnable itself.
Related
I notice, in this javadoc, https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html
that an UncaughtExceptionHandler is used for when an exception occurs but is not caught. But, will that thread fail quietly? I guess so, because it is going about its business asynchronously, but I'm investigating a related issue with one of our processes, and am surprised at only being aware of this now, 10+ years into my career.
The thread will fail quietly :)
More than a decade ago a ran into a similar problem. The performance of a system started to degrade over time. Eventually, I identified the cause: an exception was thrown in a worker thread in some custom thread pool and the worker thread was terminated. So over time, the number of live threads in the thread pool started to decrease and performance dropped.
The problem was hidden by the fact that there was no logging of the exception.
[edit]
My answer above is not correct. This is demonstrated in the below example:
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(){
public void run(){
throw new RuntimeException();
}
};
t.start();
TimeUnit.SECONDS.sleep(10);
System.out.println("done");
}
}
When the code is run, the following output is shown:
Exception in thread "Thread-0" java.lang.RuntimeException
at Main$1.run(Main.java:8)
done
So the exception is Logged.
Based on #pveentjar's updated answer I ran the following code:
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
public void run() {
throw new RuntimeException("purposeful!");
}
};
t.setUncaughtExceptionHandler((thread, throwable) -> System.out.println("uncaught: " + throwable.getMessage()));
t.start();
TimeUnit.SECONDS.sleep(10);
System.out.println("done");
}
}
, and ascertained that the uncaughtExceptionHandler seems to catch an exception from the thread that uses it, allowing the developer to do what they want with it, but that leaves the question, why bother with that handler, if not to save a system from a silent failure?
output:
uncaught: purposeful!
[a pause of approximately ten seconds]
done
I finally got to the bottom of my specific problem. It was due to shoddy error handling, allowing the thread to fail quietly:
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread() {
public void run() {
try {
//do some stuff
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("done-worker thead");
throw new RuntimeException("purposeful!");
}
};
t.setUncaughtExceptionHandler(
(thread, throwable) -> System.out.println("main thread; uncaugh exception from worker threadt: " + throwable.getMessage()));
t.start();
TimeUnit.SECONDS.sleep(10);
System.out.println("done-main thead");
}
}
In doing "some stuff", the application hit an OutOfMemoryError, which is not, strictly seaking, an Exception. Changing the above to catch(Throwable t), solved it.
I discovered this after I spend a whole day trying to find out why did the thread stopped. The cause turned out to be a simple IndexOutOfBondException. If the exception was showed in logcat I would've fixed that in a minute. Can anyone please tell me why throwing a exception in a custom thread causes a thread to stop and how can I catch it and log it?
I used ExecutorService to create and handle my custom thread.
private ExecutorService processingThread = Executors.newSingleThreadExecutor(r -> new Thread(r, "processingThread"));
I use android studio.
Code in the second screenshot is inside the function onDrawFrame() in GLRenderer.
Code in the first screenshot is inside the lambda thingy in the submit function which is in the function onDrawFrame() in GLRenderer(forgive my english).
thanks a lot
You cannot catch exception from Thread directly in your main thread.
When a thread is about to terminate due to an uncaught exception
The Java Virtual Machine will query the thread for its UncaughtExceptionHandler using Thread.getUncaughtExceptionHandler()
and will invoke the handler's uncaughtException method, passing the
thread and the exception as arguments.
If a thread has not had its UncaughtExceptionHandler explicitly set,
then its ThreadGroup object acts as its UncaughtExceptionHandler.
If the ThreadGroup object has no special requirements for dealing with
the exception, it can forward the invocation to the default uncaught
exception handler.
You can catch the runtime exception from thread as follows:
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread th, Throwable ex) {
Log.e("TEST","Uncaught exception: " + ex);
}
};
final Thread thread = new Thread() {
public void run() {
Log.d("TEST","Performing action...");
throw new RuntimeException("Exception from thread");
}
};
thread.setUncaughtExceptionHandler(h);
thread.start();
Code:
outerMethod {
#Override
public void run() {
innerMethod throws IOException
}
}
Method that exceuted in thread throws checked exception - IOException.
I need to handle this exception in main thread.
Like:
outerMethod() throws IOException
{
#Override
public void run() {
innerMethod() throws IOException
}
}
Is this possible? If no, what would be a better way to do this?
Thanks.
Use FutureTask http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/FutureTask.html#get%28%29 . It's get methods will encapsulate any exceptions from the task that might have run on another thread.
ExecutionException: Exception thrown when attempting to retrieve the result of a task that aborted by throwing an exception. This exception can be inspected using the Throwable.getCause() method.
Thread is an individual process and you cannot propagate your exception to other thread as they cannot talk through the exception route. However you can use inter thread communication and you will have to logically handle the case when an exception occurs.
From this API doc
If thread has defined UncaughtExceptionHandler, it will be invoked,
Else thread group's UncaughtExceptionHandler will be invoked if defined,
Else it can forward to default uncaught exception handler.
You have to handle exceptions inside run method :
#Override
public void run() {
try {
innerMethod();
} catch (Exception e) {
//handle e
}
Code:
public void doSomethingOrThrowUncheckedException()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
myObject.doSomething()
} catch(CheckedException e) {
new UncheckedException ();
}
}
});
worker.start();
}
Explanation
I want to perform some work in another thread that can throw a checked exception.
I cannot wait for this work to finish and I want the method caller to know if something went wrong with this work since the new thread is not able to handle the exception properly.
Is there a mechanism I can use?
Can you create a Observable outside of the thread? If something goes wrong, the thread sets a value to change that Observable. The main code is an Observer and reacts to the change when the property listener is called.
It depends on what you mean by the caller knowing that something went wrong. A couple of options come to mind immediately.
The worker thread can set an error flag. The disadvantage is that the calling thread will need to check the flag to know that something went wrong. (There can also be a flag for success; as long as neither is set, the calling thread knows that the worker is still working.
The worker thread can call an error method. The disadvantage is that the call will take place in the worker thread. On the other hand, this provides a place to take positive action. The Observer pattern might be useful here (although I think Java's implementation is terrible).
If, when the worker thread completes successfully it communicates the success to Foo, or produces an object that Foo consumes, then expand that mechanism to allow it to pass the checked exception along to Foo, rather than passing the exception to the method calling thread.
public void doSomething()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
result = myObject.doSomething();
foo.processResult(result);
} catch(CheckedException e) {
foo.processException(e);
}
}
});
worker.start();
}
public void doSomething()
{
Thread worker = new Thread(new Runnable() {
public void run() {
try {
result = myObject.doSomething();
resultQueue.add(result);
} catch(CheckedException e) {
resultQueue.add(e);
}
}
});
worker.start();
}
If doSomething() doesn't interact with anything when it successfully completes then you'll need to follow one of the other answers.
You may also want to have a look at uncaughtExceptionhandler.
I am creating some multi-threaded code, and I have created a JobDispatcher class that creates threads. I want this object to handle any unhandled exceptions in the worker threads, and so I am using
Thread.setUncaughtExceptionHandler(this);
Now, I would like to test this functionality - how can I generate an unhandled exception in the run() method of my worker object?
Just throw any exception.
E.g.:
throw new RuntimeException("Testing unhandled exception processing.");
Complete:
public class RuntimeTest
{
public static void main(String[] a)
{
Thread t = new Thread()
{
public void run()
{
throw new RuntimeException("Testing unhandled exception processing.");
}
};
t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e)
{
System.err.println(t + "; " + e);
}
});
t.start();
}
}
What's the problem with just throwing an exception:
throw new Exception("This should be unhandled");
Inside your run method. And of course, not catching it. It should trigger your handler.
You should throw some unchecked exception. An unchecked exception does not require your code to handle it, and is therefore a good candidate to make all the way down the call stack.
You can choose RuntimeException for example, or even something like AssertionError, if you want to minimize the chances that some part of the code catches the exception and handles it before it reaches your handler.
just add this code and you'll get unhandled exception without lint error:
int i = 1/0;