Suppose I have 5 threads belonging to a thread group named "Fruits-group".
How can I assign UncaughtExceptionHandler to all threads of Fruits-group at one go?
I know we can define a global UncaughtExceptionHandler for all threads.
What I am looking for is assigning a UncaughtExceptionHandler to an entire thread-group?
TL;DR Subclass the ThreadGroup and override the uncaughtException() method.
A ThreadGroup is an UncaughtExceptionHandler, implementing the uncaughtException(Thread t, Throwable e) method:
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:
If this thread group has a parent thread group, the uncaughtException method of that parent is called with the same two arguments.
Otherwise, this method checks to see if there is a default uncaught exception handler installed, and if so, its uncaughtException method is called with the same two arguments.
Otherwise, this method determines if the Throwable argument is an instance of ThreadDeath. If so, nothing special is done. Otherwise, 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.
Applications can override this method in subclasses of ThreadGroup to provide alternative handling of uncaught exceptions.
UPDATE
If you want to be able to set an UncaughtExceptionHandler for the ThreadGroup, you can create a delegating subclass:
public class ExceptionHandlingThreadGroup extends ThreadGroup {
private UncaughtExceptionHandler uncaughtExceptionHandler;
public ExceptionHandlingThreadGroup(String name) {
super(name);
}
public ExceptionHandlingThreadGroup(ThreadGroup parent, String name) {
super(parent, name);
}
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return this.uncaughtExceptionHandler;
}
public void setUncaughtExceptionHandler(UncaughtExceptionHandler uncaughtExceptionHandler) {
this.uncaughtExceptionHandler = uncaughtExceptionHandler;
}
#Override
public void uncaughtException(Thread t, Throwable e) {
if (this.uncaughtExceptionHandler != null)
this.uncaughtExceptionHandler.uncaughtException(t, e);
else
super.uncaughtException(t, e);
}
}
In general, though, it would likely be better to just implement the exception handling logic directly in the subclass, but this way, you can use an existing UncaughtExceptionHandler implementation.
Related
I've read through several examples of how to use an UncaughtExceptionHandler to pass exceptions from a nested thread to a parent thread. Currently, my nested thread's UncaughtExceptionHandler catches exceptions as it should. I've set it to pass exceptions to the parent thread's default UncaughtExceptionHandler.uncaughtException(...) method.
public void load() {
// Create the nested thread
final Thread loadingThread = new Thread(new Runnable() {
#Override
public void run() {
// Do stuff... throw an exception at some point
throw new RuntimeException("Something has gone horribly wrong!");
}
}
});
// Set up a custom exception handler for the nested thread
class LoadingThreadExceptionHandler implements UncaughtExceptionHandler {
// The parent exception handler
private UncaughtExceptionHandler defaultHandler;
// Constructor to get a handle on the parent's exception handler
public void LoadingThreadExceptionHandler() {
// Check if the parent thread has an exception handler
if (Thread.getDefaultUncaughtExceptionHandler() == null) {
System.out.println("The default handler is null");
}
// Get the parent's default exception handler
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
return;
}
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.prinln("This is the nested thread's handler");
// Pass it onto the parent's default exception handler
defaultHandler.uncaughtException(t, e);
}
};
// Set the custom exception handler on the loadingThread
loadingThread.setUncaughtExceptionHandler(new LoadingThreadExceptionHandler());
// Start the thread
loadingThread.start();
return;
}
Running this produces the following output:
This is the nested thread's handler
For whatever reason, the nested UncaughtExceptionHandler is called, but it doesn't seem to pass the exception to the parent thread's default UncaughtExceptionHandler, as nothing happens after that point. I did at one point suspect maybe the parent's default UncaughtExceptionHandler was null so, I added some logic in the constructor to check for this and print a message, but this doesn't seem to ever be the case. I've also attempted overriding the parent's default exception handler as well, although to no avail.
Am I missing something here? I cannot, for the life of me, understand why the parent's uncaughtException(...) method never seems to be called.
public void LoadingThreadExceptionHandler()
This is not being called, because it's not the constructor. When you invoked new LoadingThreadExceptionHandler(), the no-arg default constructor (which is created by the compiler if no constructor exists) is invoked.
To fix it, it should be without a return type:
public LoadingThreadExceptionHandler()
I wrote an android app for killing background running processes which is performed in a background thread. And I use below class to create my own simple thread framework.
public final class ThreadPool {
private static final ExecutorService sES = Executors.newCachedThreadPool();
public static Future<?> runNow(Runnable task) {
return sES.submit(task);
}
}
However, a serious problem occured. That is the exception(unchecked exception) would be consumed by Executor framework quitely. So I don't know why the ActivityManager.killBackgroundProcesses() method does not work. After spending 2 or 3 hours and I wrote some log at almost every method invoke point, I found this method requires android.permission.KILL_BACKGROUND_PROCESSES permission, otherwise, it would throw a SecurityException that is an unchecked exception. The key is this exception is consumed by Excecutor framework, so I cannot see any exception information at logcat and the app does not crash at all and runs weird.
Of course, I don't know that at first, so I spent a lot of time to find out that reason, mainly depending on two posts:
Handling exceptions from Java ExecutorService tasks and
Catching thread exceptions from Java ExecutorService
So I changed the my ThreadPool class as:
public final class ThreadPool {
private static final ExecutorService sES = Executors.newCachedThreadPool();
/*
* submit(Runnable) and execute(Runnable) method has
* big difference. Especially in Exception handling!!!
* You have to pay attention.
*/
public static Future<?> submitNow(Runnable task) {
return sES.submit(task);
}
public static void executeNow(Runnable task) {
sES.execute(task);
}
}
But I still have below question:
Why Sun/Oracle decide to consume the exception instead of transfer to users to handle if submit(Runnable command) method is used?
How can I change this behavior to handle unchecked exception according to my own need if I insist using submit() method?
And my doubts are:
If submit(Runnable command) method is used, I know the exception result can be get by Future.get() method. But, if we use Future.get() method to judge if an exception occured, the thread Future object located in would be block. That is not what we expect in most case, I suppose.
I also learned Executor.execute() method handles exception like common Thread.start(). But there is no return value. So the task cannot be shut down at any time. Users have no ability to shut down any running thread by Future.cancel() method when leaving activity.
If you call get() on the future, you will get an ExecutionException if the underlying operation (callable) threw an exception. See the docs.
You can't change this behavior (from point 1. )
The reason why this is implemented this way is the following: submit is a non blocking call. The job gets posted in the executor and executed at a later time.
Only when the job is executed do you know if it crashed or not, so only when you try to access the result of the job do you get the exception.
Finally, I find a good solution.
We can extend Thread and invoke setUncaughtHandler() in the constructor like below.
public class MyThread1 extends Thread {
public MyThread1(Runnable task) {
super(task);
setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("thread throws an uncaught exception at thread id: " + t.getId());
}
});
}
}
And then customize a ThreadFactory like following.
public class MyThreadFactory1 implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
return new MyThread1(r, "Peace");
}
}
So we can call the factory method in Executors like following.
ExecutorService es = Executors.newSingleThreadExecutor(new MyThreadFactory1());
So we can detect the uncaught exception happened in thread.
In a threaded environment, unchecked exceptions are known to be notorious and weird behaviors could occur like threads dying, no exception log etc.
One good way is to wrap the runnable object in a thread. Create a thread group and add the thread to the thread group.
final ThreadGroup group = new ThreadGroup("<a name for the thread group>");
public static Future<?> submitNow(Runnable task) {
//Create a thread wrapping the runnable task and specify the thread group
Thread t = new Thread(group,task);
return sES.submit(task);
}
The ThreadGroup class has its uncaughtException(Thread, Throwable) method which is automatically called by the JVM if a thread encountered an exception and is uncaught in your code. See http://developer.android.com/reference/java/lang/ThreadGroup.html
You can also change the behavior by creating your own ThreadGroup object and overriding the uncaughtException method:
public class MyThreadGroup extends ThreadGroup {
#Override
public void uncaughtException(Thread t, Throwable e) {
//do what you need to do to handle the exception
}
}
Or you can assign an UncaughtExceptionHandler to the current Thread.
public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread t, Throwable t2) {
//Implement
}
}
Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
Or set the default exception handler:
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
I am trying to catch all unhandled exceptions that occur in a service
that runs in a separate process. In the onCreate for the service, I call
a method that calls Thread.setDefaultUncaughtExceptionHandler with
MyCustomExceptionHandler class. My examination of the logs indicates
that it is set but does not consistently get called for uncaught
exceptions. For example, when I hard code a divide by zero into the
service, it does not get called at all. Another example is a
NullPointerException that I forced which resulted in a call to my
handler but the stack trace did not point to the actual lines of code
that caused the exception.
public class ActivityEngineService extends android.app.Service {
/** Called when the service is first created. */
#Override
public void onCreate() {
super.onCreate();
setUncaughtExceptionHandler();
// Get the service that has a hard coded divide by zero running
}
public void setUncaughtExceptionHandler() {
Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());
System.out.println("Thread.getDefaultUncaughtExceptionHandler(): " + Thread.getDefaultUncaughtExceptionHandler());
}
public class CustomExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultUEH;
public CustomExceptionHandler() {
this.defaultUEH = Thread.getDefaultUncaughtExceptionHandler();
}
public void uncaughtException(Thread t, Throwable e) {
System.out.println("CustomExceptionHandler uncaughtException e: " + e.getMessage());
defaultUEH.uncaughtException(t, e);
}
}
}
According to javadoc:
Sets the default uncaught exception handler. This handler is invoked in case any Thread dies due to an unhandled exception.
As far as I know in your case whole process is dying, that's why uncaughtException does not invoke. It will invoked if you will have uncaught exceptions inside separate threads.
I am writing an app that will make use of multiple threads. There is main thread that is launching another threads. What i want to acomplish is when one of the launched threads throws an exception, the main thread should stop launching threads. It looks more or less like this:
class SomeClass {
boolean launchNewThread = true;
public static void main() {
while (launchNewThread) {
try {
AnotherClass.run();
} catch (CrossThreadException e) {
launchNewThread = false;
}
}
}
}
class AnotherClass implements Runnable {
public void run() {
if (a=0) throw new CrossThreadException();
}
}
You should do it yourself - catch the exception and pass it somehow into the launching thread.
Also, there is Future concept, which does it already. You should launch your threads as futures and check isDone(), and catch ExecutionException from get(), this exception will be thrown if a future's task thrown an exception.
You can also use a listener as described in How to throw a checked exception from a java thread?
When an exception is thrown inside one of the child threads, you could call a method like listener.setLaunchNewThread(false) from the child thread which will change the value of your boolean flag in the parent thread.
On a side note, calling AnotherClass.run() does not start a new thread but only call the run method from AnotherClass within the same thread. Use new Thread(new AnotherClass()).start() instead.
Suppose that I have a method which spawns a new thread and do some work. Under certain conditions, the newly spawn thread would throw a certain type of exception, which terminates the entire process. I would like to write JUnit tests to verify this behavior. Is there a way to do it?
The method is:
private void foo() {
new Thread() {
#Override void run() {
throw new CertainException("exception messages");
}
}.start();
}
In test (conceptually):
public testExceptionThrownFromNewThread() throws Exception {
try {
foo();
Thread.sleep(5000); // wait for the exception to be thrown
fail();
} catch (CertainException e) {
assertEquals(e.message, "exception messages");
}
}
This test doesn't work because the exception spawn from the other thread cannot be caught.
If you want to test just the code inside of the run() method, refactor it ouf of the foo() method (probably into a Runnable) and test it separately without running it from a thread.
private void foo() {
new Thread(new MyRunnable()).start();
}
public class MyRunnable implements Runnable {
public void run() {
....
}
}
Now you can instantiate a MyRunnable object and call the run() method from your test without needing to start a thread.
EDIT
Testing of the thread creation could be done by using a ThreadFactory Mock. (as Jon Skeet pointed out).
You could overwrite the default UncaughtExceptionHandler for Threads. It gets called whenever a Thread throws an exception. In this handler, you can check whether the expected exception is equal to the thrown exception and e.g. test for messages or count the occurences of the exception. By using a CountDownLatch, you can also check whether the exceptions are thrown in time and how many of them you expect.
This works even if you do not have access to the Thread created by the class under test. If you have access to it though, there is certainly an easier approach, e.g. refactoring the class under test and introduce an Exception Listener or alike. Make the class under test better testable also improves the design, e.g. by removing the dependency on Threads and directly test the body of the run() method which you could externalize.
public class ThreadExceptionTest {
private void foo() {
new Thread(new Runnable() {
#Override
public void run() {
throw new RuntimeException("exception messages");
}
}).start();
}
#Test
public void testFoo() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final RuntimeException expectedException = new RuntimeException("exception messages");
UncaughtExceptionHandler eh = new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
if (e.getMessage().equals(expectedException.getMessage()))
latch.countDown();
}
};
Thread.setDefaultUncaughtExceptionHandler(eh);
foo();
assertTrue(latch.await(100,TimeUnit.MILLISECONDS));
}
}
Well, unit tests are supposed to verify results of method calls, not implementation details.
In your library, if thread terminates, how does it affect library user? Maybe computations won't be finished and end results won't be recored in database? Then check database. Maybe thread will stop doing some periodic tasks (like cleanup)? Then check whether cleanup is still being done.
And if exception thrown won't affect user in any way, then there's nothing to check. Because whether exception is thrown or not is just an implementation details (user will never see it).
One option is to make the capability to start a thread a dependency - which you can specify using the existing ThreadFactory interface. Then in your unit test you can provide a specialist ThreadFactory which wraps the given Runnable in order to record exceptions etc.
You'll be able to test that:
The ThreadFactory was used
The thread was started
The operation threw an exception