Blob Blame Raw
From a174f452fc48735da7ee49ab5c906528f87b77b5 Mon Sep 17 00:00:00 2001
From: Jakub Filak <jfilak@redhat.com>
Date: Thu, 9 Jan 2014 22:56:28 +0100
Subject: [PATCH 26/39] Surround all JNI calls in try catch all block

Related to rhbz#1051198
---
 src/abrt-checker.c            | 273 ++++++++++++++++++------------------------
 src/jthrowable_circular_buf.c |  40 ++++++-
 2 files changed, 155 insertions(+), 158 deletions(-)

diff --git a/src/abrt-checker.c b/src/abrt-checker.c
index fb0c0eb..b6f11e8 100644
--- a/src/abrt-checker.c
+++ b/src/abrt-checker.c
@@ -631,6 +631,26 @@ static void report_stacktrace(
 
 
 /*
+ * Returns logical true if exception occurred and clears it.
+ */
+static inline int check_and_clear_exception(
+        JNIEnv     *jni_env)
+{
+        if ((*jni_env)->ExceptionOccurred(jni_env))
+        {
+#ifdef VERBOSE
+            (*jni_env)->ExceptionDescribe(jni_env);
+#endif
+            (*jni_env)->ExceptionClear(jni_env);
+            return 1;
+        }
+
+        return 0;
+}
+
+
+
+/*
  * Print a message when any JVM TI error occurs.
  */
 static void print_jvmti_error(
@@ -666,12 +686,13 @@ static int get_tid(
     }
 
     jmethodID get_id = (*jni_env)->GetMethodID(jni_env, thread_class, "getId", "()J" );
-    if (NULL == get_id)
+    if (check_and_clear_exception(jni_env) || NULL == get_id)
     {
-        VERBOSE_PRINT("Cannot method java.lang.Thread.getId()J\n");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/lang/Thread.getId()J\n");
         return 1;
     }
 
+    /* Thread.getId() throws nothing */
     *tid = (*jni_env)->CallLongMethod(jni_env, thr, get_id);
 
     return 0;
@@ -908,7 +929,6 @@ static void get_thread_name(
 }
 
 
-
 /*
  * Read executable name from link /proc/${PID}/exe
  */
@@ -1068,7 +1088,7 @@ static char *get_main_class(
     char *class_name;
 
     error_code = (*jvmti_env)->GetSystemProperty(jvmti_env, "sun.java.command", &class_name);
-    if (error_code != JVMTI_ERROR_NONE)
+    if (error_code != JVMTI_ERROR_NONE || NULL == class_name)
     {
         return UNKNOWN_CLASS_NAME;
     }
@@ -1081,26 +1101,10 @@ static char *get_main_class(
     string_replace(class_name, '.', '/');
 
     jclass cls = (*jni_env)->FindClass(jni_env, class_name);
-    /* Throws:
-     * ClassFormatError: if the class data does not specify a valid class. 
-     * ClassCircularityError: if a class or interface would be its own superclass or superinterface. 
-     * NoClassDefFoundError: if no definition for a requested class or interface can be found. 
-     * OutOfMemoryError: if the system runs out of memory.
-     */
-
-    jthrowable exception;
-    exception = (*jni_env)->ExceptionOccurred(jni_env);
-    if (exception)
+    if (check_and_clear_exception(jni_env) || cls == NULL)
     {
-        (*jni_env)->ExceptionClear(jni_env);
-    }
-
-    if (cls == NULL)
-    {
-        if (class_name != NULL)
-        {
-            (*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)class_name);
-        }
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of %s\n", class_name);
+        (*jvmti_env)->Deallocate(jvmti_env, (unsigned char*)class_name);
         return UNKNOWN_CLASS_NAME;
     }
 
@@ -1428,6 +1432,7 @@ static char* get_path_to_class_class_loader(
             char     *class_name,
             const char *stringize_method_name)
 {
+    char *out = NULL;
     jclass class_loader_class = NULL;
 
     char *upd_class_name = (char*)malloc(strlen(class_name) + sizeof("class") + 1);
@@ -1442,47 +1447,18 @@ static char* get_path_to_class_class_loader(
 
     /* find ClassLoader class */
     class_loader_class = (*jni_env)->FindClass(jni_env, "java/lang/ClassLoader");
-    /* Throws:
-     * ClassFormatError: if the class data does not specify a valid class. 
-     * ClassCircularityError: if a class or interface would be its own superclass or superinterface. 
-     * NoClassDefFoundError: if no definition for a requested class or interface can be found. 
-     * OutOfMemoryError: if the system runs out of memory.
-     */
-
-    /* check if exception was thrown from FindClass() method */
-    jthrowable exception;
-    exception = (*jni_env)->ExceptionOccurred(jni_env);
-    if (exception)
-    {
-        (*jni_env)->ExceptionClear(jni_env);
-        free(upd_class_name);
-        return NULL;
-    }
-
-    if (class_loader_class ==  NULL)
+    if (check_and_clear_exception(jni_env) || class_loader_class ==  NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/lang/ClassLoader\n");
         free(upd_class_name);
         return NULL;
     }
 
     /* find method ClassLoader.getResource() */
-    jmethodID get_resource = (*jni_env)->GetMethodID(jni_env, class_loader_class, "getResource", "(Ljava/lang/String;)Ljava/net/URL;" );
-    /* Throws:
-     * NoSuchMethodError: if the specified method cannot be found. 
-     * ExceptionInInitializerError: if the class initializer fails due to an exception. 
-     * OutOfMemoryError: if the system runs out of memory.
-     */
-
-    exception = (*jni_env)->ExceptionOccurred(jni_env);
-    if (exception)
-    {
-        free(upd_class_name);
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        return NULL;
-    }
-
-    if (get_resource ==  NULL)
+    jmethodID get_resource = (*jni_env)->GetMethodID(jni_env, class_loader_class, "getResource", "(Ljava/lang/String;)Ljava/net/URL;");
+    if (check_and_clear_exception(jni_env) || get_resource ==  NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/lang/ClassLoader.getResource(Ljava/lang/String;)Ljava/net/URL;\n");
         free(upd_class_name);
         (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
         return NULL;
@@ -1491,52 +1467,46 @@ static char* get_path_to_class_class_loader(
     /* convert new class name into a Java String */
     jstring j_class_name = (*jni_env)->NewStringUTF(jni_env, upd_class_name);
     free(upd_class_name);
+    if (check_and_clear_exception(jni_env))
+    {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not allocate a new UTF string for '%s'\n", upd_class_name);
+        goto get_path_to_class_class_loader_lcl_refs_cleanup;
+    }
 
     /* call method ClassLoader.getResource(className) */
     jobject url = (*jni_env)->CallObjectMethod(jni_env, class_loader, get_resource, j_class_name);
-    if ((*jni_env)->ExceptionCheck(jni_env))
+    if (check_and_clear_exception(jni_env) || NULL == url)
     {
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        (*jni_env)->DeleteLocalRef(jni_env, j_class_name);
-        (*jni_env)->ExceptionClear(jni_env);
-        return NULL;
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a resource of %s\n", class_name);
+        goto get_path_to_class_class_loader_lcl_refs_cleanup;
     }
-    if (url ==  NULL)
+
+    /* find method URL.toString() */
+    jclass url_class = (*jni_env)->FindClass(jni_env, "java/net/URL");
+    if (check_and_clear_exception(jni_env) || NULL == url_class)
     {
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        (*jni_env)->DeleteLocalRef(jni_env, j_class_name);
-        return NULL;
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/net/URL\n");
+        goto get_path_to_class_class_loader_lcl_refs_cleanup;
     }
 
-    /* find method URL.toString() */
-    jmethodID to_external_form = (*jni_env)->GetMethodID(jni_env, (*jni_env)->FindClass(jni_env, "java/net/URL"), stringize_method_name, "()Ljava/lang/String;" );
-    /* Throws:
-     * NoSuchMethodError: if the specified method cannot be found. 
-     * ExceptionInInitializerError: if the class initializer fails due to an exception. 
-     * OutOfMemoryError: if the system runs out of memory.
-     */
-    exception = (*jni_env)->ExceptionOccurred(jni_env);
-    if (exception)
+    jmethodID to_external_form = (*jni_env)->GetMethodID(jni_env, url_class, stringize_method_name, "()Ljava/lang/String;");
+    if (check_and_clear_exception(jni_env) || NULL == to_external_form)
     {
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        (*jni_env)->DeleteLocalRef(jni_env, j_class_name);
-        return NULL;
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/net/URL.%s()Ljava/lang/String;\n", stringize_method_name);
+        goto get_path_to_class_class_loader_lcl_refs_cleanup;
     }
 
     /* call method URL.toString() */
     jstring jstr = (jstring)(*jni_env)->CallObjectMethod(jni_env, url, to_external_form);
-    /* no exception expected */
-
-    if (jstr ==  NULL)
+    if (check_and_clear_exception(jni_env) || jstr ==  NULL)
     {
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        (*jni_env)->DeleteLocalRef(jni_env, j_class_name);
-        return NULL;
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Failed to convert an URL object to a string\n");
+        goto get_path_to_class_class_loader_lcl_refs_cleanup;
     }
 
     /* convert Java String into C char* */
     char *str = (char*)(*jni_env)->GetStringUTFChars(jni_env, jstr, NULL);
-    char *out = strdup(str);
+    out = strdup(str);
     if (out == NULL)
     {
         fprintf(stderr, "strdup(): out of memory");
@@ -1544,6 +1514,8 @@ static char* get_path_to_class_class_loader(
 
     /* cleanup */
     (*jni_env)->ReleaseStringUTFChars(jni_env, jstr, str);
+
+get_path_to_class_class_loader_lcl_refs_cleanup:
     (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
     (*jni_env)->DeleteLocalRef(jni_env, j_class_name);
     return out;
@@ -1558,39 +1530,30 @@ static jobject get_system_class_loader(
             jvmtiEnv *jvmti_env __UNUSED_VAR,
             JNIEnv   *jni_env)
 {
+    jobject system_class_loader = NULL;
+
     jclass class_loader_class = (*jni_env)->FindClass(jni_env, "java/lang/ClassLoader");
-    if (NULL == class_loader_class)
+    if (check_and_clear_exception(jni_env) || NULL == class_loader_class)
     {
-        VERBOSE_PRINT("Cannot find java/lang/ClassLoader class\n");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/lang/ClassLoader\n");
         return NULL;
     }
 
     jmethodID get_system_class_loader_smethod =(*jni_env)->GetStaticMethodID(jni_env, class_loader_class, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
-    jthrowable exception = (*jni_env)->ExceptionOccurred(jni_env);
-    if (NULL != exception)
-    {
-        VERBOSE_PRINT("Exception occured: can not get method java.lang.ClassLoader.getSystemClassLoader()\n");
-        (*jni_env)->ExceptionClear(jni_env);
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        return NULL;
-    }
-    if (NULL == get_system_class_loader_smethod)
+    if (check_and_clear_exception(jni_env) || NULL == get_system_class_loader_smethod)
     {
-        VERBOSE_PRINT("Cannot find java.lang.ClassLoader.getSystemClassLoader()Ljava/lang/ClassLoader;\n");
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        return NULL;
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not find method java.lang.ClassLoader.getSystemClassLoader()Ljava/lang/ClassLoader;\n");
+        goto get_system_class_loader_cleanup;
     }
 
-    jobject system_class_loader = (*jni_env)->CallStaticObjectMethod(jni_env, class_loader_class, get_system_class_loader_smethod);
-    exception = (*jni_env)->ExceptionOccurred(jni_env);
-    if (NULL != exception)
+    system_class_loader = (*jni_env)->CallStaticObjectMethod(jni_env, class_loader_class, get_system_class_loader_smethod);
+    if (check_and_clear_exception(jni_env))
     {
-        VERBOSE_PRINT("java.lang.ClassLoader.getSystemClassLoader() thrown an exception\n");
-        (*jni_env)->ExceptionClear(jni_env);
-        (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
-        return NULL;
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Exception occurred: Cannot get the system class loader\n");
+        goto get_system_class_loader_cleanup;
     }
 
+get_system_class_loader_cleanup:
     (*jni_env)->DeleteLocalRef(jni_env, class_loader_class);
     return system_class_loader;
 }
@@ -1613,12 +1576,12 @@ static char* get_path_to_class(
     /* class is loaded using boot classloader */
     if (class_loader == NULL)
     {
-        VERBOSE_PRINT("A class has not been loaded by a ClassLoader. Going to use the system class loader.\n");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": A class has not been loaded by a ClassLoader. Going to use the system class loader.\n");
 
         class_loader = get_system_class_loader(jvmti_env, jni_env);
         if (NULL == class_loader)
         {
-            VERBOSE_PRINT("Cannot get the system class loader.");
+            VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Cannot get the system class loader.");
             return NULL;
         }
     }
@@ -1642,16 +1605,16 @@ static jclass find_class_in_loaded_class(
     }
 
     jclass class_class = (*jni_env)->FindClass(jni_env, "java/lang/Class");
-    if (NULL == class_class)
+    if (check_and_clear_exception(jni_env) || NULL == class_class)
     {
-        VERBOSE_PRINT("Cannot find java/lang/Class class");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of java/lang/Class\n");
         goto find_class_in_loaded_class_cleanup;
     }
 
     jmethodID get_name_method = (*jni_env)->GetMethodID(jni_env, class_class, "getName", "()Ljava/lang/String;");
-    if (NULL == get_name_method)
+    if (check_and_clear_exception(jni_env) || NULL == get_name_method)
     {
-        VERBOSE_PRINT("Cannot find java.lang.Class.getName.()Ljava/lang/String;");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of java/lang/Class.getName()Ljava/lang/String;\n");
         (*jni_env)->DeleteLocalRef(jni_env, class_class);
         goto find_class_in_loaded_class_cleanup;
     }
@@ -1659,8 +1622,9 @@ static jclass find_class_in_loaded_class(
     for (jint i = 0; NULL == result && i < num_classes; ++i)
     {
         jobject class_name = (*jni_env)->CallObjectMethod(jni_env, loaded_classes[i], get_name_method);
-        if (NULL == class_name)
+        if (check_and_clear_exception(jni_env) || NULL == class_name)
         {
+            VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get name of a loaded class\n");
             continue;
         }
 
@@ -1697,21 +1661,17 @@ static int print_stack_trace_element(
 {
     jclass stack_frame_class = (*jni_env)->GetObjectClass(jni_env, stack_frame);
     jmethodID get_class_name_method = (*jni_env)->GetMethodID(jni_env, stack_frame_class, "getClassName", "()Ljava/lang/String;");
-    if (get_class_name_method == NULL)
+    if (check_and_clear_exception(jni_env) || get_class_name_method == NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Frame class).getClassName()Ljava/lang/String;\n");
         (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class);
         return -1;
     }
 
     jstring class_name_of_frame_method = (*jni_env)->CallObjectMethod(jni_env, stack_frame, get_class_name_method);
-    if ((*jni_env)->ExceptionOccurred(jni_env))
-    {
-        (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class);
-        (*jni_env)->ExceptionClear(jni_env);
-        return -1;
-    }
-    if (class_name_of_frame_method == NULL)
+    if (check_and_clear_exception(jni_env) || class_name_of_frame_method == NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class name of a class on a frame\n");
         (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class);
         return -1;
     }
@@ -1721,11 +1681,9 @@ static int print_stack_trace_element(
     jclass class_of_frame_method = (*jni_env)->FindClass(jni_env, cls_name_str);
     char *class_location = NULL;
 
-    if ((*jni_env)->ExceptionOccurred(jni_env))
+    if (check_and_clear_exception(jni_env) || NULL == class_of_frame_method)
     {
-        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": FindClass(%s) thrown an exception\n", cls_name_str);
-        (*jni_env)->ExceptionClear(jni_env);
-
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get class of %s. Try more hard by searching in the loaded classes.\n", cls_name_str);
         string_replace(cls_name_str, '/', '.');
         class_of_frame_method = find_class_in_loaded_class(jvmti_env, jni_env, cls_name_str);
         string_replace(cls_name_str, '.', '/');
@@ -1753,20 +1711,16 @@ static int print_stack_trace_element(
 
     jmethodID to_string_method = (*jni_env)->GetMethodID(jni_env, stack_frame_class, "toString", "()Ljava/lang/String;");
     (*jni_env)->DeleteLocalRef(jni_env, stack_frame_class);
-    if (to_string_method == NULL)
+    if (check_and_clear_exception(jni_env) || to_string_method == NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Frame class).toString()Ljava/lang/String;\n");
         return -1;
     }
 
     jobject orig_str = (*jni_env)->CallObjectMethod(jni_env, stack_frame, to_string_method);
-    if ((*jni_env)->ExceptionOccurred(jni_env))
-    {
-        (*jni_env)->DeleteLocalRef(jni_env, orig_str);
-        (*jni_env)->ExceptionClear(jni_env);
-        return -1;
-    }
-    if (orig_str == NULL)
+    if (check_and_clear_exception(jni_env) || NULL == orig_str)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a string representation of a class on a frame\n");
         (*jni_env)->DeleteLocalRef(jni_env, orig_str);
         return -1;
     }
@@ -1801,21 +1755,17 @@ static int print_exception_stack_trace(
 
     jclass exception_class = (*jni_env)->GetObjectClass(jni_env, exception);
     jmethodID to_string_method = (*jni_env)->GetMethodID(jni_env, exception_class, "toString", "()Ljava/lang/String;");
-    if (to_string_method == NULL)
+    if (check_and_clear_exception(jni_env) || to_string_method == NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Exception class).toString()Ljava/lang/String;\n");
         (*jni_env)->DeleteLocalRef(jni_env, exception_class);
         return -1;
     }
 
     jobject exception_str = (*jni_env)->CallObjectMethod(jni_env, exception, to_string_method);
-    if ((*jni_env)->ExceptionCheck(jni_env))
-    {
-        (*jni_env)->DeleteLocalRef(jni_env, exception_class);
-        (*jni_env)->ExceptionClear(jni_env);
-        return -1;
-    }
-    if (exception_str == NULL)
+    if (check_and_clear_exception(jni_env) || exception_str == NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a string representation of a class on a frame\n");
         (*jni_env)->DeleteLocalRef(jni_env, exception_class);
         return -1;
     }
@@ -1840,26 +1790,23 @@ static int print_exception_stack_trace(
     jmethodID get_stack_trace_method = (*jni_env)->GetMethodID(jni_env, exception_class, "getStackTrace", "()[Ljava/lang/StackTraceElement;");
     (*jni_env)->DeleteLocalRef(jni_env, exception_class);
 
-    if (get_stack_trace_method == NULL)
+    if (check_and_clear_exception(jni_env) || get_stack_trace_method == NULL)
     {
-        VERBOSE_PRINT("Cannot get getStackTrace() method id");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Exception class).getStackTrace()[Ljava/lang/StackTraceElement;\n");
         return wrote;
     }
 
     jobject stack_trace_array = (*jni_env)->CallObjectMethod(jni_env, exception, get_stack_trace_method);
-    if ((*jni_env)->ExceptionCheck(jni_env))
-    {
-        (*jni_env)->ExceptionClear(jni_env);
-        return wrote;
-    }
-    if (stack_trace_array ==  NULL)
+    if (check_and_clear_exception(jni_env) || stack_trace_array ==  NULL)
     {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get a stack trace from an exception object\n");
         return wrote;
     }
 
     jint array_size = (*jni_env)->GetArrayLength(jni_env, stack_trace_array);
     for (jint i = 0; i < array_size; ++i)
     {
+        /* Throws only ArrayIndexOutOfBoundsException and this should not happen */
         jobject frame_element = (*jni_env)->GetObjectArrayElement(jni_env, stack_trace_array, i);
 
         const int frame_wrote = print_stack_trace_element(jvmti_env,
@@ -1918,23 +1865,30 @@ static char *generate_thread_stack_trace(
 
     wrote += exception_wrote;
 
+    /* GetObjectClass() throws nothing */
     jclass exception_class = (*jni_env)->GetObjectClass(jni_env, exception);
     if (NULL == exception_class)
     {
-        VERBOSE_PRINT("Cannot get class of an object\n");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Cannot get class of an object\n");
         return stack_trace_str;
     }
 
     jmethodID get_cause_method = (*jni_env)->GetMethodID(jni_env, exception_class, "getCause", "()Ljava/lang/Throwable;");
     (*jni_env)->DeleteLocalRef(jni_env, exception_class);
 
-    if (NULL == get_cause_method)
+    if (check_and_clear_exception(jni_env) || NULL == get_cause_method)
     {
-        VERBOSE_PRINT("Cannot find get an id of getCause()Ljava/lang/Throwable; method\n");
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Could not get methodID of $(Exception class).getCause()Ljava/lang/Throwable;\n");
         return stack_trace_str;
     }
 
     jobject cause = (*jni_env)->CallObjectMethod(jni_env, exception, get_cause_method);
+    if (check_and_clear_exception(jni_env))
+    {
+        VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Failed to get an inner exception of the top most one;\n");
+        return stack_trace_str;
+    }
+
     while (NULL != cause)
     {
         if ((size_t)(MAX_STACK_TRACE_STRING_LENGTH - wrote) < (sizeof(CAUSED_STACK_TRACE_HEADER) - 1))
@@ -1965,6 +1919,11 @@ static char *generate_thread_stack_trace(
 
         jobject next_cause = (*jni_env)->CallObjectMethod(jni_env, cause, get_cause_method);
         (*jni_env)->DeleteLocalRef(jni_env, cause);
+        if (check_and_clear_exception(jni_env))
+        {
+            VERBOSE_PRINT(__FILE__ ":" STRINGIZE(__LINE__)": Failed to get an inner exception of another inner one;\n");
+            return stack_trace_str;
+        }
         cause = next_cause;
     }
 
@@ -2318,14 +2277,14 @@ static void JNICALL callback_on_exception_catch(
     }
 
     jclass object_class = (*jni_env)->FindClass(jni_env, "java/lang/Object");
-    if (NULL == object_class)
+    if (check_and_clear_exception(jni_env) || NULL == object_class)
     {
         VERBOSE_PRINT("Cannot find java/lang/Object class");
         goto callback_on_exception_catch_exit;
     }
 
     jmethodID equal_method = (*jni_env)->GetMethodID(jni_env, object_class, "equals", "(Ljava/lang/Object;)Z");
-    if (NULL == equal_method)
+    if (check_and_clear_exception(jni_env) || NULL == equal_method)
     {
         VERBOSE_PRINT("Cannot find java.lang.Object.equals(Ljava/lang/Object;)Z method");
         (*jni_env)->DeleteLocalRef(jni_env, object_class);
@@ -2333,8 +2292,12 @@ static void JNICALL callback_on_exception_catch(
     }
 
     jboolean equal_objects = (*jni_env)->CallBooleanMethod(jni_env, exception_object, equal_method, rpt->exception_object);
-    if (!equal_objects)
+    if (check_and_clear_exception(jni_env) || !equal_objects)
+    {
+        VERBOSE_PRINT("Cannot determine whether the caught exception is also the uncaught exception");
+        (*jni_env)->DeleteLocalRef(jni_env, object_class);
         goto callback_on_exception_catch_exit;
+    }
 
     /* Faster than get()-pop() approach is faster because it is search-and-search-free but
      * pop()-push() approach is search-free-and-search-malloc
diff --git a/src/jthrowable_circular_buf.c b/src/jthrowable_circular_buf.c
index e13801c..64f0f30 100644
--- a/src/jthrowable_circular_buf.c
+++ b/src/jthrowable_circular_buf.c
@@ -162,6 +162,16 @@ static int jthrowable_circular_buf_find_index(T_jthrowableCircularBuf *buffer, j
     }
 
     jclass object_class = (*buffer->jni_env)->FindClass(buffer->jni_env, "java/lang/Object");
+    if ((*buffer->jni_env)->ExceptionOccurred(buffer->jni_env))
+    {
+        VERBOSE_PRINT("Cannot find java/lang/Object class\n");
+#ifdef VERBOSE
+        (*buffer->jni_env)->ExceptionDescribe(buffer->jni_env);
+#endif
+        (*buffer->jni_env)->ExceptionClear(buffer->jni_env);
+        return 1;
+    }
+
     if (NULL == object_class)
     {
         VERBOSE_PRINT("Cannot find java/lang/Object class");
@@ -169,6 +179,16 @@ static int jthrowable_circular_buf_find_index(T_jthrowableCircularBuf *buffer, j
     }
 
     jmethodID equal_method = (*buffer->jni_env)->GetMethodID(buffer->jni_env, object_class, "equals", "(Ljava/lang/Object;)Z");
+    if ((*buffer->jni_env)->ExceptionOccurred(buffer->jni_env))
+    {
+        VERBOSE_PRINT("Cannot find java.lang.Object.equals(Ljava/lang/Object;)Z method\n");
+#ifdef VERBOSE
+        (*buffer->jni_env)->ExceptionDescribe(buffer->jni_env);
+#endif
+        (*buffer->jni_env)->ExceptionClear(buffer->jni_env);
+        return 1;
+    }
+
     if (NULL == equal_method)
     {
         VERBOSE_PRINT("Cannot find java.lang.Object.equals(Ljava/lang/Object;)Z method");
@@ -182,10 +202,24 @@ static int jthrowable_circular_buf_find_index(T_jthrowableCircularBuf *buffer, j
     for (size_t i = rbegin; /* break inside */; i = jthrowable_circular_buf_get_index(buffer, (i - 1)))
     {
         VERBOSE_PRINT("Checking next exception object %p\n", (void *)buffer->mem[i]);
-        if (NULL != buffer->mem[i] && (*buffer->jni_env)->CallBooleanMethod(buffer->jni_env, buffer->mem[i], equal_method, exception))
+        if (NULL != buffer->mem[i])
         {
-            *index = i;
-            return 0;
+            jboolean equals = (*buffer->jni_env)->CallBooleanMethod(buffer->jni_env, buffer->mem[i], equal_method, exception);
+            if ((*buffer->jni_env)->ExceptionOccurred(buffer->jni_env))
+            {
+                VERBOSE_PRINT("Cannot determine whether objects are equal\n");
+#ifdef VERBOSE
+                (*buffer->jni_env)->ExceptionDescribe(buffer->jni_env);
+#endif
+                (*buffer->jni_env)->ExceptionClear(buffer->jni_env);
+                return 1;
+            }
+
+            if (equals)
+            {
+                *index = i;
+                return 0;
+            }
         }
 
         if (rend == i)
-- 
1.8.3.1