Задачу я решил, но правильно ли я понимаю причину, почему исходный код не работал? Метод setDefaultUncaughtExceptionHandler статический:
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
Описание:
Set the default handler invoked when a thread abruptly terminates due to an uncaught exception, and no other handler has been defined for that thread.
Uncaught exception handling is controlled first by the thread, then by the thread's ThreadGroup object and finally by the default uncaught exception handler. If the thread does not have an explicit uncaught exception handler set, and the thread's thread group (including parent thread groups) does not specialize its uncaughtException method, then the default handler's uncaughtException method will be invoked.

By setting the default uncaught exception handler, an application can change the way in which uncaught exceptions are handled (such as logging to a specific device, or file) for those threads that would already accept whatever "default" behavior the system provided.

Note that the default uncaught exception handler should not usually defer to the thread's ThreadGroup object, as that could cause infinite recursion.

Parameters:
eh - the object to use as the default uncaught exception handler. If null then there is no default handler.
Throws:
SecurityException - if a security manager is present and it denies RuntimePermission ("setDefaultUncaughtExceptionHandler")
Since:
1.5
Метод setUncaughtExceptionHandler нестатический:
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
Описание:
Set the handler invoked when this thread abruptly terminates due to an uncaught exception.
A thread can take full control of how it responds to uncaught exceptions by having its uncaught exception handler explicitly set. If no such handler is set then the thread's ThreadGroup object acts as its handler.

Parameters:
eh - the object to use as this thread's uncaught exception handler. If null then this thread has no explicit handler.
Throws:
SecurityException - if the current thread is not allowed to modify this thread.
Since:
1.5
handler у нас статический:
public static Thread.UncaughtExceptionHandler handler = new OurUncaughtExceptionHandler();
Не работало потому, что у нас setUncaughtExceptionHandler был не статический? А заработало потому, что поменяли на setDefaultUncaughtExceptionHandler , который является статическим? Или тут какая-то другая причина? https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html