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.
Related
I have multiple methods running concurrently on different threads. If an exception occurs and isn't handled on any of the threads, I want it to propagate back to the calling method (see example below).
public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(3);
pool.execute(new Thread1Class());//Thread 1 of many
//...
}
}
class Thread1Class implements Runnable{
#Override
public void run() {
try {
throw new InterruptedException(); //How do I propogate this to the main method?
} catch (InterruptedException e) {
System.out.println("An unchecked exception was caught here");
}
}
}
The threads must implement Runnable since Callable will block the threads from running concurrently.
I followed the method of Overriding protected void afterExecute(Runnable r, Throwable t) shown as the accepted answer here: Handling exceptions from Java ExecutorService tasks. If I understand correct, this solution will only handle unchecked exceptions. How should I deal with the checked exceptions?
If I understand correct, this solution will only handle unchecked exceptions. How should I deal with the checked exceptions
No, the afterExecute(Runnable, Throwable) would catch any RuntimeException or checked exception. According to the docs at https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html
If non-null, the Throwable is the uncaught RuntimeException or Error that caused execution to terminate abruptly.
Edit:
Sorry for the misunderstanding,
If you want to propagate the checked exception to the caller, you would need to wrap it in a RuntimeException
InterruptedException a;
throw new RuntimeException("wrapped", a);
The executor:
protected void afterExecute(Runnable r, Throwable t){
Throwable root = t.getCause();
}
Or you could create your own runtime exception type.
Is there a way to create a listener in a separate class that runs a certain piece of code whenever an exception is caught within your project?
My code has a lot of try-catches in it, and if an exception is caught I would like to see the logs using log4j. I can do the following for every try-catch I have fairly easily (just with some time effort):
private static final Logger logger = LogManager.getLogger(Example.class);
public void testMethod() {
try {
// some code here that could throw an exception
} catch(Exception e) {
logger.error("Unexpected error has occurred: ", e);
}
}
This will log the exception using log4j. However, I would need to do that over 50 times, and it's so redundant that I would rather be able to use 1 method to do that. So, is there a way to instead do something like this?
public class ListenerClass {
private static final Logger logger = LogManager.getLogger(ListenerClass.class);
// This method will be listening for exceptions to be caught within the project
/**
* #param e - The exception that was just caught
*/
public void listenerMethod(ExceptionCaught e) {
logger.error("An exception has been thrown: ", e);
}
}
Is this possible?
Thanks
Standard java way:
Thread.setDefaultUncaughtExceptionHandler( (thread, throwable) -> {
log(throwable.getMessage(), thread.getId());
});
which will handle uncaught RuntimeExceptions, and unless otherwise specified it will act for all your application threads.
Just remember the Exceptions are thrown for a reason, and shouldn't be ignored, especially RuntimeExceptions.
If you are using an older version of java (before 8), you must explicitly instantiate an anonymous class:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(final Thread t, final Throwable e) {
}
});
Look at Thread.setDefaultUncaughtExceptionHandler()
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'm unsure why the uncaughtException method is not being invoke.
static
{
/**
* Register a logger for unhandled exceptions.
*/
Thread.UncaughtExceptionHandler globalExceptionHandler = new Thread.UncaughtExceptionHandler()
{
#Override
public void uncaughtException(Thread t, Throwable e)
{
System.out.println("handle exception."); // can also set bp here that is not hit.
}
};
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
Thread.currentThread().setUncaughtExceptionHandler(globalExceptionHandler);
/**
* Register gateway listen port.
*/
try
{
// some stuff that raises an IOException
}
catch (IOException e)
{
System.out.println("Throwing exception");
throw new RuntimeException(e);
}
}
The program output is:
Throwing exception
java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: java.io.FileNotFoundException: blah.jks
(The system cannot find the file specified)
...some stack trace...
Exception in thread "main"
Process finished with exit code 1
The RuntimeException being raised from a static initializer, it happens when your main class is loaded. It is then caught by the system class loader, which wraps it into an ExceptionInInitializerError, then exits from the JVM. Since the exception is caught, your default uncaught exception handler is never invoked.
Your code is throwing an IOException, and your catch catches an IOException. The IOException is caught and handled. IIRC the UncaughtExceptionHandler only deals with uncaught exception from within normal code, not from within a catch. Try changing your catch temporarily to catch some other exception, and see what happens. Don't forget to change it back afterwards!
Your code is in static block. Unless on very rare case of JVM implemenation ( if any), static block is not where you should handle any errors or exceptions if possible. This is because you don't have that much of control on the execution of static block ( unless you have dynamic class loader), which is pretty rare.
So if it is fair, move your code to instance block and it should work fine.
So when something unexpected happens in your static block, your application is expected not to continue.
So basically , all those unexpected exceptions in static block will be represented by ExceptionInIntiializerError.
You can refer to here
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());