I believe there are free tools to do it, but even making your own tool is easy. JVMTI will help.
Here is a simple JVMTI agent I made to trace all exceptions:
#include <jni.h>
#include <jvmti.h>
#include <string.h>
#include <stdio.h>
void JNICALL ExceptionCallback(jvmtiEnv* jvmti, JNIEnv* env, jthread thread,
                               jmethodID method, jlocation location, jobject exception,
                               jmethodID catch_method, jlocation catch_location) {
    char* class_name;
    jclass exception_class = (*env)->GetObjectClass(env, exception);
    (*jvmti)->GetClassSignature(jvmti, exception_class, &class_name, NULL);
    printf("Exception: %s\n", class_name);
}
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM* vm, char* options, void* reserved) {
    jvmtiEnv* jvmti;
    jvmtiEventCallbacks callbacks;
    jvmtiCapabilities capabilities;
    (*vm)->GetEnv(vm, (void**)&jvmti, JVMTI_VERSION_1_0);
    memset(&capabilities, 0, sizeof(capabilities));
    capabilities.can_generate_exception_events = 1;
    (*jvmti)->AddCapabilities(jvmti, &capabilities);
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.Exception = ExceptionCallback;
    (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
    (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_EXCEPTION, NULL);
    return 0;
}
To use it, make a shared library (.so) from the given source code, and run Java with -agentpath option:
java -agentpath:libextrace.so MyApplication
This will log all exception class names on stdout. ExceptionCallback also receives a thread, a method and a location where the exception occured, so you can extend the callback to print much more details.